mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-24 07:05:34 -07:00
Display logic expressions in a table.
This commit is contained in:
parent
a15ab88f47
commit
9ca342ddc3
3 changed files with 196 additions and 114 deletions
|
@ -355,14 +355,15 @@ class Parser {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
std::unique_ptr<LogicExpression> LogicExpression::Parse(const std::string& exprStr) {
|
std::shared_ptr<LogicExpression> LogicExpression::Parse(const std::string& exprStr) {
|
||||||
Parser parser(exprStr);
|
Parser parser(exprStr);
|
||||||
std::shared_ptr<LogicExpression::Impl> impl = parser.Parse();
|
std::shared_ptr<LogicExpression::Impl> impl = parser.Parse();
|
||||||
|
|
||||||
std::function<std::unique_ptr<LogicExpression>(const std::shared_ptr<LogicExpression::Impl>&)> populateChildren;
|
std::function<std::shared_ptr<LogicExpression>(const std::shared_ptr<LogicExpression::Impl>&)> populateChildren;
|
||||||
populateChildren = [&](const std::shared_ptr<LogicExpression::Impl>& impl) {
|
populateChildren = [&](const std::shared_ptr<LogicExpression::Impl>& impl) {
|
||||||
auto expr = std::make_unique<LogicExpression>();
|
auto expr = std::make_shared<LogicExpression>();
|
||||||
expr->impl = impl;
|
expr->impl = impl;
|
||||||
|
impl->expression = expr;
|
||||||
for (const auto& child : impl->children) {
|
for (const auto& child : impl->children) {
|
||||||
expr->children.emplace_back(populateChildren(child));
|
expr->children.emplace_back(populateChildren(child));
|
||||||
}
|
}
|
||||||
|
@ -372,7 +373,7 @@ std::unique_ptr<LogicExpression> LogicExpression::Parse(const std::string& exprS
|
||||||
return populateChildren(impl);
|
return populateChildren(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<LogicExpression>>& LogicExpression::GetChildren() const {
|
const std::vector<std::shared_ptr<LogicExpression>>& LogicExpression::GetChildren() const {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,8 +562,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::EvaluateFunction(const std:
|
||||||
|
|
||||||
// If callback is provided, call it with function info
|
// If callback is provided, call it with function info
|
||||||
if (callback) {
|
if (callback) {
|
||||||
std::string exprStr = functionName + "(" + (children.empty() ? "" : "...") + ")";
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
callback(exprStr, path, depth, GetTypeString(), result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -854,7 +854,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::EvaluateArithmetic(char op,
|
||||||
exprStr = "Unknown expression";
|
exprStr = "Unknown expression";
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(exprStr, path, depth, opStr, result);
|
callback(expression, path, depth, opStr, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -902,7 +902,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString(), result);
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
@ -913,7 +913,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
auto childResult = children[0]->Evaluate(path + ".0", depth + 1, callback);
|
auto childResult = children[0]->Evaluate(path + ".0", depth + 1, callback);
|
||||||
result = !GetValue<bool>(childResult);
|
result = !GetValue<bool>(childResult);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString(), result);
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -924,7 +924,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
if (!GetValue<bool>(leftResult)) {
|
if (!GetValue<bool>(leftResult)) {
|
||||||
result = false;
|
result = false;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString() + " (short-circuit)", result);
|
callback(expression, path, depth, GetTypeString() + " (short-circuit)", result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -932,7 +932,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
auto rightResult = children[1]->Evaluate(path + ".1", depth + 1, callback);
|
auto rightResult = children[1]->Evaluate(path + ".1", depth + 1, callback);
|
||||||
result = GetValue<bool>(rightResult);
|
result = GetValue<bool>(rightResult);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString(), result);
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -943,7 +943,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
if (GetValue<bool>(leftResult)) {
|
if (GetValue<bool>(leftResult)) {
|
||||||
result = true;
|
result = true;
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString() + " (short-circuit)", result);
|
callback(expression, path, depth, GetTypeString() + " (short-circuit)", result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -951,7 +951,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
auto rightResult = children[1]->Evaluate(path + ".1", depth + 1, callback);
|
auto rightResult = children[1]->Evaluate(path + ".1", depth + 1, callback);
|
||||||
result = GetValue<bool>(rightResult);
|
result = GetValue<bool>(rightResult);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString(), result);
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -997,7 +997,7 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
try {
|
try {
|
||||||
result = std::visit(compare, leftResult, rightResult);
|
result = std::visit(compare, leftResult, rightResult);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString(), result);
|
callback(expression, path, depth, GetTypeString(), result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (const std::bad_variant_access&) {
|
} catch (const std::bad_variant_access&) {
|
||||||
|
@ -1025,7 +1025,8 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(exprText, path, depth, GetTypeString() + (cond ? " (true branch)" : " (false branch)"), result);
|
callback(expression, path, depth, GetTypeString() + (cond ? " (true branch)" : " (false branch)"),
|
||||||
|
result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1038,16 +1039,19 @@ LogicExpression::ValueVariant LogicExpression::Impl::Evaluate(const std::string&
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpressionEvaluation EvaluateExpression(std::string condition) {
|
ExpressionEvaluation EvaluateExpression(std::string condition) {
|
||||||
const auto& expression = LogicExpression::Parse(condition);
|
return EvaluateExpression(LogicExpression::Parse(condition));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionEvaluation EvaluateExpression(std::shared_ptr<LogicExpression> expression) {
|
||||||
// Create a vector to store the evaluation sequence
|
// Create a vector to store the evaluation sequence
|
||||||
std::vector<std::tuple<std::string, std::string, int, std::string, LogicExpression::ValueVariant>>
|
std::vector<std::tuple<std::shared_ptr<LogicExpression>, std::string, int, std::string, LogicExpression::ValueVariant>>
|
||||||
evaluationSequence;
|
evaluationSequence;
|
||||||
|
|
||||||
// Define a callback that records each evaluation step
|
// Define a callback that records each evaluation step
|
||||||
auto recordCallback = [&evaluationSequence](const std::string& exprStr, const std::string& path, int depth,
|
auto recordCallback = [&evaluationSequence](const std::shared_ptr<LogicExpression>& expr,
|
||||||
|
const std::string& path, int depth,
|
||||||
const std::string& type, const LogicExpression::ValueVariant& result) {
|
const std::string& type, const LogicExpression::ValueVariant& result) {
|
||||||
evaluationSequence.emplace_back(exprStr, path, depth, type, result);
|
evaluationSequence.emplace_back(expr, path, depth, type, result);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Evaluate the expression with the callback
|
// Evaluate the expression with the callback
|
||||||
|
|
|
@ -14,11 +14,11 @@ class LogicExpression {
|
||||||
public:
|
public:
|
||||||
using ValueVariant = std::variant<bool, int, uint8_t, uint16_t>;
|
using ValueVariant = std::variant<bool, int, uint8_t, uint16_t>;
|
||||||
// Define callback type for evaluation tracing
|
// Define callback type for evaluation tracing
|
||||||
using EvaluationCallback = std::function<void(const std::string&, const std::string&, int, const std::string&, const ValueVariant&)>;
|
using EvaluationCallback = std::function<void(const std::shared_ptr<LogicExpression>&, const std::string&, int, const std::string&, const ValueVariant&)>;
|
||||||
|
|
||||||
static std::unique_ptr<LogicExpression> Parse(const std::string& exprStr);
|
static std::shared_ptr<LogicExpression> Parse(const std::string& exprStr);
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
const std::vector<std::unique_ptr<LogicExpression>>& GetChildren() const;
|
const std::vector<std::shared_ptr<LogicExpression>>& GetChildren() const;
|
||||||
|
|
||||||
// Add optional callback parameter to Evaluate
|
// Add optional callback parameter to Evaluate
|
||||||
template <typename T> T Evaluate(const EvaluationCallback& callback = nullptr) const {
|
template <typename T> T Evaluate(const EvaluationCallback& callback = nullptr) const {
|
||||||
|
@ -68,6 +68,7 @@ class LogicExpression {
|
||||||
Impl* parent;
|
Impl* parent;
|
||||||
size_t startIndex;
|
size_t startIndex;
|
||||||
size_t endIndex;
|
size_t endIndex;
|
||||||
|
std::shared_ptr<LogicExpression> expression;
|
||||||
|
|
||||||
// Modified to accept path and depth
|
// Modified to accept path and depth
|
||||||
ValueVariant Evaluate(const std::string& path = "0", int depth = 0, const EvaluationCallback& callback = nullptr) const;
|
ValueVariant Evaluate(const std::string& path = "0", int depth = 0, const EvaluationCallback& callback = nullptr) const;
|
||||||
|
@ -293,14 +294,14 @@ class LogicExpression {
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Impl> impl;
|
std::shared_ptr<Impl> impl;
|
||||||
std::vector<std::unique_ptr<LogicExpression>> children;
|
std::vector<std::shared_ptr<LogicExpression>> children;
|
||||||
|
|
||||||
friend class Parser;
|
friend class Parser;
|
||||||
friend bool IsEnumConstant(const std::string& s);
|
friend bool IsEnumConstant(const std::string& s);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExpressionEvaluation {
|
struct ExpressionEvaluation {
|
||||||
std::string Expression;
|
std::shared_ptr<LogicExpression> Expression;
|
||||||
int Depth;
|
int Depth;
|
||||||
std::string Type;
|
std::string Type;
|
||||||
LogicExpression::ValueVariant Result;
|
LogicExpression::ValueVariant Result;
|
||||||
|
@ -309,4 +310,6 @@ struct ExpressionEvaluation {
|
||||||
|
|
||||||
ExpressionEvaluation EvaluateExpression(std::string condition);
|
ExpressionEvaluation EvaluateExpression(std::string condition);
|
||||||
|
|
||||||
|
ExpressionEvaluation EvaluateExpression(std::shared_ptr<LogicExpression> expression);
|
||||||
|
|
||||||
std::string ToString(const LogicExpression::ValueVariant& value);
|
std::string ToString(const LogicExpression::ValueVariant& value);
|
|
@ -15,11 +15,21 @@ uint64_t GetUnixTimestamp();
|
||||||
|
|
||||||
struct LogicTrackerCheck {
|
struct LogicTrackerCheck {
|
||||||
struct Region {
|
struct Region {
|
||||||
|
struct ExpressionRow {
|
||||||
|
std::shared_ptr<LogicExpression> Expression;
|
||||||
|
std::vector<ExpressionRow> Children;
|
||||||
|
std::optional<LogicExpression::ValueVariant> ChildDay;
|
||||||
|
std::optional<LogicExpression::ValueVariant> ChildNight;
|
||||||
|
std::optional<LogicExpression::ValueVariant> AdultDay;
|
||||||
|
std::optional<LogicExpression::ValueVariant> AdultNight;
|
||||||
|
bool Expanded;
|
||||||
|
};
|
||||||
|
|
||||||
std::string RegionName;
|
std::string RegionName;
|
||||||
std::unique_ptr<ExpressionEvaluation> ChildDay;
|
ExpressionRow Root;
|
||||||
std::unique_ptr<ExpressionEvaluation> ChildNight;
|
bool CombineAll = false;
|
||||||
std::unique_ptr<ExpressionEvaluation> AdultDay;
|
bool CombineChild = false;
|
||||||
std::unique_ptr<ExpressionEvaluation> AdultNight;
|
bool CombineAdult = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string CheckName;
|
std::string CheckName;
|
||||||
|
@ -28,6 +38,61 @@ struct LogicTrackerCheck {
|
||||||
|
|
||||||
static std::vector<LogicTrackerCheck> checks;
|
static std::vector<LogicTrackerCheck> checks;
|
||||||
|
|
||||||
|
LogicTrackerCheck::Region::ExpressionRow CreateExpressionRows(const std::shared_ptr<LogicExpression>& expression) {
|
||||||
|
LogicTrackerCheck::Region::ExpressionRow row;
|
||||||
|
row.Expression = expression;
|
||||||
|
row.Expanded = false;
|
||||||
|
|
||||||
|
const auto& children = expression->GetChildren();
|
||||||
|
row.Children.reserve(children.size());
|
||||||
|
for (const auto& child : children) {
|
||||||
|
row.Children.emplace_back(CreateExpressionRows(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AgeTime {
|
||||||
|
ChildDay,
|
||||||
|
ChildNight,
|
||||||
|
AdultDay,
|
||||||
|
AdultNight
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void PopulateExpressionValues(LogicTrackerCheck::Region::ExpressionRow& row, const ExpressionEvaluation& eval, AgeTime ageTime) {
|
||||||
|
if (ageTime == AgeTime::ChildDay) {
|
||||||
|
row.ChildDay = eval.Result;
|
||||||
|
} else if (ageTime == AgeTime::ChildNight) {
|
||||||
|
row.ChildNight = eval.Result;
|
||||||
|
} else if (ageTime == AgeTime::AdultDay) {
|
||||||
|
row.AdultDay = eval.Result;
|
||||||
|
} else if (ageTime == AgeTime::AdultNight) {
|
||||||
|
row.AdultNight = eval.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& rowChild : row.Children) {
|
||||||
|
for (const auto& evalChild : eval.Children) {
|
||||||
|
if (row.Expression == eval.Expression) {
|
||||||
|
PopulateExpressionValues(rowChild, evalChild, ageTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::tuple<bool, bool, bool> CalculateCombines(const LogicTrackerCheck::Region::ExpressionRow& row) {
|
||||||
|
bool combineChild = row.ChildDay == row.ChildNight;
|
||||||
|
bool combineAdult = row.AdultDay == row.AdultNight;
|
||||||
|
bool combineAll = combineChild && combineAdult && row.ChildDay == row.AdultDay;
|
||||||
|
for (const auto& child : row.Children) {
|
||||||
|
auto [childCombineAll, childCombineChild, childCombineAdult] = CalculateCombines(child);
|
||||||
|
combineAll &= childCombineAll;
|
||||||
|
combineChild &= childCombineChild;
|
||||||
|
combineAdult &= childCombineAdult;
|
||||||
|
}
|
||||||
|
return {combineAll, combineChild, combineAdult};
|
||||||
|
}
|
||||||
|
|
||||||
void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
checks.clear();
|
checks.clear();
|
||||||
|
|
||||||
|
@ -41,13 +106,15 @@ void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
if (locationAccess.GetLocation() == check) {
|
if (locationAccess.GetLocation() == check) {
|
||||||
LogicTrackerCheck::Region regionAgeTime;
|
LogicTrackerCheck::Region regionAgeTime;
|
||||||
regionAgeTime.RegionName = region.regionName;
|
regionAgeTime.RegionName = region.regionName;
|
||||||
|
regionAgeTime.Root = CreateExpressionRows(LogicExpression::Parse(locationAccess.GetConditionStr()));
|
||||||
|
regionAgeTime.Root.Expanded = true;
|
||||||
|
|
||||||
if (region.childDay) {
|
if (region.childDay) {
|
||||||
logic->IsChild = true;
|
logic->IsChild = true;
|
||||||
logic->AtDay = true;
|
logic->AtDay = true;
|
||||||
|
|
||||||
regionAgeTime.ChildDay =
|
const auto& eval = EvaluateExpression(regionAgeTime.Root.Expression);
|
||||||
std::make_unique<ExpressionEvaluation>(EvaluateExpression(locationAccess.GetConditionStr()));
|
PopulateExpressionValues(regionAgeTime.Root, eval, AgeTime::ChildDay);
|
||||||
|
|
||||||
logic->IsChild = false;
|
logic->IsChild = false;
|
||||||
logic->AtDay = false;
|
logic->AtDay = false;
|
||||||
|
@ -56,8 +123,8 @@ void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
logic->IsChild = true;
|
logic->IsChild = true;
|
||||||
logic->AtNight = true;
|
logic->AtNight = true;
|
||||||
|
|
||||||
regionAgeTime.ChildNight =
|
const auto& eval = EvaluateExpression(regionAgeTime.Root.Expression);
|
||||||
std::make_unique<ExpressionEvaluation>(EvaluateExpression(locationAccess.GetConditionStr()));
|
PopulateExpressionValues(regionAgeTime.Root, eval, AgeTime::ChildNight);
|
||||||
|
|
||||||
logic->IsChild = false;
|
logic->IsChild = false;
|
||||||
logic->AtNight = false;
|
logic->AtNight = false;
|
||||||
|
@ -66,8 +133,8 @@ void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
logic->IsAdult = true;
|
logic->IsAdult = true;
|
||||||
logic->AtDay = true;
|
logic->AtDay = true;
|
||||||
|
|
||||||
regionAgeTime.AdultDay =
|
const auto& eval = EvaluateExpression(regionAgeTime.Root.Expression);
|
||||||
std::make_unique<ExpressionEvaluation>(EvaluateExpression(locationAccess.GetConditionStr()));
|
PopulateExpressionValues(regionAgeTime.Root, eval, AgeTime::AdultDay);
|
||||||
|
|
||||||
logic->IsAdult = false;
|
logic->IsAdult = false;
|
||||||
logic->AtDay = false;
|
logic->AtDay = false;
|
||||||
|
@ -76,13 +143,18 @@ void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
logic->IsAdult = true;
|
logic->IsAdult = true;
|
||||||
logic->AtNight = true;
|
logic->AtNight = true;
|
||||||
|
|
||||||
regionAgeTime.AdultNight =
|
const auto& eval = EvaluateExpression(regionAgeTime.Root.Expression);
|
||||||
std::make_unique<ExpressionEvaluation>(EvaluateExpression(locationAccess.GetConditionStr()));
|
PopulateExpressionValues(regionAgeTime.Root, eval, AgeTime::AdultNight);
|
||||||
|
|
||||||
logic->IsAdult = false;
|
logic->IsAdult = false;
|
||||||
logic->AtNight = false;
|
logic->AtNight = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto [combineAll, combineChild, combineAdult] = CalculateCombines(regionAgeTime.Root);
|
||||||
|
regionAgeTime.CombineAll = combineAll;
|
||||||
|
regionAgeTime.CombineChild = combineChild;
|
||||||
|
regionAgeTime.CombineAdult = combineAdult;
|
||||||
|
|
||||||
logicTrackerCheck.Regions.emplace_back(std::move(regionAgeTime));
|
logicTrackerCheck.Regions.emplace_back(std::move(regionAgeTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,110 +162,113 @@ void LogicTrackerWindow::ShowRandomizerCheck(RandomizerCheck check) {
|
||||||
|
|
||||||
checks.emplace_back(std::move(logicTrackerCheck));
|
checks.emplace_back(std::move(logicTrackerCheck));
|
||||||
|
|
||||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Logic Tracker")->Show();
|
auto window = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Logic Tracker");
|
||||||
|
window->Show();
|
||||||
|
ImGui::SetWindowFocus(window->GetName().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TruncateText(const std::string& text, float maxWidth) {
|
static std::string ToString(const std::optional<LogicExpression::ValueVariant>& value) {
|
||||||
ImVec2 textSize = ImGui::CalcTextSize(text.c_str());
|
if (!value.has_value()) {
|
||||||
if (textSize.x <= maxWidth)
|
return "";
|
||||||
return text;
|
|
||||||
|
|
||||||
std::string truncated = text;
|
|
||||||
// Remove characters until the text fits with the ellipsis appended
|
|
||||||
while (!truncated.empty() && ImGui::CalcTextSize((truncated + "...").c_str()).x > maxWidth) {
|
|
||||||
truncated.pop_back();
|
|
||||||
}
|
}
|
||||||
return truncated + "...";
|
return ToString(value.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawExpression(const ExpressionEvaluation& expression) {
|
static void DrawExpressionRow(const LogicTrackerCheck::Region& region, LogicTrackerCheck::Region::ExpressionRow& row,
|
||||||
ImGuiTreeNodeFlags treeNodeFlags =
|
int level) {
|
||||||
expression.Children.empty() ? ImGuiTreeNodeFlags_Leaf : ImGuiTreeNodeFlags_DefaultOpen;
|
ImGui::TableNextRow();
|
||||||
|
if (level > 0) {
|
||||||
|
ImGui::Indent(10.0f);
|
||||||
|
}
|
||||||
|
|
||||||
float availableWidth = ImGui::GetContentRegionAvail().x - ImGui::GetTreeNodeToLabelSpacing();
|
ImGui::TableNextColumn();
|
||||||
auto text = TruncateText(ToString(expression.Result) + " = " + expression.Expression, availableWidth);
|
ImGui::Text("%d", level);
|
||||||
|
|
||||||
if (ImGui::TreeNodeEx(&expression, treeNodeFlags, "%s", text.c_str())) {
|
ImGui::TableNextColumn();
|
||||||
if (!expression.Children.empty()) {
|
ImGui::TextWrapped("%s", row.Expression->ToString().c_str());
|
||||||
for (const auto& child : expression.Children) {
|
|
||||||
DrawExpression(child);
|
ImGui::TableNextColumn();
|
||||||
}
|
ImGui::TextUnformatted(ToString(row.ChildDay).c_str());
|
||||||
|
|
||||||
|
if (!region.CombineAll) {
|
||||||
|
if (!region.CombineChild) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(ToString(row.ChildNight).c_str());
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(ToString(row.AdultDay).c_str());
|
||||||
|
|
||||||
|
if (!region.CombineAdult) {
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(ToString(row.AdultNight).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& child : row.Children) {
|
||||||
|
//if (child.Expanded) {
|
||||||
|
DrawExpressionRow(region, child, level + 1);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (level > 0) {
|
||||||
|
ImGui::Unindent(10.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawCheckRegion(const LogicTrackerCheck::Region& region) {
|
static void DrawCheckRegion(LogicTrackerCheck::Region& region) {
|
||||||
if (ImGui::TreeNodeEx(region.RegionName.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
|
int columnCount = 3;
|
||||||
if (region.ChildDay != nullptr) {
|
if (!region.CombineAll) {
|
||||||
bool resultString = LogicExpression::GetValue<bool>(region.ChildDay->Result);
|
if (!region.CombineChild) {
|
||||||
if (ImGui::TreeNodeEx(region.ChildDay.get(), ImGuiTreeNodeFlags_DefaultOpen, "Child-Day Result: %s",
|
columnCount += 1;
|
||||||
resultString ? "true" : "false")) {
|
|
||||||
DrawExpression(*region.ChildDay);
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ImGui::TreeNodeEx("Child-Day Inaccessible", ImGuiTreeNodeFlags_Leaf)) {
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
columnCount += 1;
|
||||||
if (region.ChildNight != nullptr) {
|
if (!region.CombineAdult) {
|
||||||
bool resultString = LogicExpression::GetValue<bool>(region.ChildNight->Result);
|
columnCount += 1;
|
||||||
if (ImGui::TreeNodeEx(region.ChildNight.get(), ImGuiTreeNodeFlags_DefaultOpen, "Child-Night Result: %s",
|
|
||||||
resultString ? "true" : "false")) {
|
|
||||||
DrawExpression(*region.ChildNight);
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ImGui::TreeNodeEx("Child-Night Inaccessible", ImGuiTreeNodeFlags_Leaf)) {
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (region.AdultDay != nullptr) {
|
|
||||||
bool resultString = LogicExpression::GetValue<bool>(region.AdultDay->Result);
|
|
||||||
if (ImGui::TreeNodeEx(region.AdultDay.get(), ImGuiTreeNodeFlags_DefaultOpen, "Adult-Day Result: %s",
|
|
||||||
resultString ? "true" : "false")) {
|
|
||||||
DrawExpression(*region.AdultDay);
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ImGui::TreeNodeEx("Adult-Day Inaccessible", ImGuiTreeNodeFlags_Leaf)) {
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region.AdultNight != nullptr) {
|
|
||||||
bool resultString = LogicExpression::GetValue<bool>(region.AdultNight->Result);
|
|
||||||
if (ImGui::TreeNodeEx(region.AdultNight.get(), ImGuiTreeNodeFlags_DefaultOpen, "Adult-Night Result: %s",
|
|
||||||
resultString ? "true" : "false")) {
|
|
||||||
DrawExpression(*region.AdultNight);
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ImGui::TreeNodeEx("Adult-Night Inaccessible", ImGuiTreeNodeFlags_Leaf)) {
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TreePop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginTable(region.RegionName.c_str(), columnCount,
|
||||||
|
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) {
|
||||||
|
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("Expression", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
if (region.CombineAll) {
|
||||||
|
ImGui::TableSetupColumn("All", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
} else {
|
||||||
|
if (region.CombineChild) {
|
||||||
|
ImGui::TableSetupColumn("Child", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
} else {
|
||||||
|
ImGui::TableSetupColumn("Child Day", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("Child Night", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
}
|
||||||
|
if (region.CombineAdult) {
|
||||||
|
ImGui::TableSetupColumn("Adult", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
} else {
|
||||||
|
ImGui::TableSetupColumn("Adult Day", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
ImGui::TableSetupColumn("Adult Night", ImGuiTableColumnFlags_WidthFixed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawExpressionRow(region, region.Root, 0);
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DrawCheck(const LogicTrackerCheck& check) {
|
static void DrawCheck(LogicTrackerCheck& check) {
|
||||||
ImGui::SeparatorText(("Check: " + check.CheckName).c_str());
|
ImGui::SeparatorText(("Check: " + check.CheckName).c_str());
|
||||||
if (check.Regions.empty()) {
|
if (check.Regions.empty()) {
|
||||||
ImGui::Text("No regions found for this check.");
|
ImGui::Text("No regions found for this check.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto& region : check.Regions) {
|
for (auto& region : check.Regions) {
|
||||||
DrawCheckRegion(region);
|
DrawCheckRegion(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogicTrackerWindow::DrawElement() {
|
void LogicTrackerWindow::DrawElement() {
|
||||||
for (const auto& check : checks) {
|
for (auto& check : checks) {
|
||||||
DrawCheck(check);
|
DrawCheck(check);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue