Skip to content

Commit

Permalink
introduced new and easier rule system
Browse files Browse the repository at this point in the history
  • Loading branch information
ChriZ982 committed Jan 4, 2018
1 parent 4c596f2 commit 6d1218b
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 195 deletions.
4 changes: 2 additions & 2 deletions OpenHab2RulesGenerator/OpenHab2RulesGenerator.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,17 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\File.cpp" />
<ClCompile Include="src\Optimizer.cpp" />
<ClCompile Include="src\Parser.cpp" />
<ClCompile Include="src\Main.cpp" />
<ClCompile Include="src\Optimizer.cpp" />
<ClCompile Include="src\Rule.cpp" />
<ClCompile Include="src\StringUtils.cpp" />
<ClCompile Include="src\Template.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\File.h" />
<ClInclude Include="src\Parser.h" />
<ClInclude Include="src\Optimizer.h" />
<ClInclude Include="src\Parser.h" />
<ClInclude Include="src\Rule.h" />
<ClInclude Include="src\StringUtils.h" />
<ClInclude Include="src\Template.h" />
Expand Down
44 changes: 19 additions & 25 deletions OpenHab2RulesGenerator/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,38 @@ int main() {
std::cout << "Fixed rules file: " << fixed_file << "\n";
std::cout << "Template rules file: " << template_file << "\n\n";

std::cout << "(1/9) Reading rules from file\n";
auto rules = zohrg::read_rules_from_file(in_lines);
std::cout << "\tparsed " << rules.size() << " rules\n";

std::cout << "(2/9) Reading fixed rules from file\n";
auto fixed_lines = zohrg::read_file(fixed_file);
std::cout << "\t" << fixed_lines.size() << " lines\n";

std::cout << "(3/9) Reading templates from file\n";
std::cout << "(1/8) Reading templates from file\n";
const std::vector<std::string> template_lines = zohrg::read_file(template_file);
std::cout << "\t" << template_lines.size() << " lines\n";
auto templates = zohrg::read_templates_from_file(template_lines);
std::cout << "\tparsed " << templates.size() << " templates\n";

std::cout << "(4/9) Creating rules file\n";
auto out_lines = create_rules_file(rules, templates);
std::cout << "(2/8) Reading rules from file\n";
auto rules = read_rules_from_file(in_lines, templates);
std::cout << "\tparsed " << rules.size() << " rules\n";

std::cout << "(3/8) Reading fixed rules from file\n";
auto fixed_lines = zohrg::read_file(fixed_file);
std::cout << "\t" << fixed_lines.size() << " lines\n";

std::cout << "(5/9) Grouping rules by condition\n";
out_lines = zohrg::group_by_condition(out_lines);
std::cout << "(4/8) Optimizing rules\n";
rules = optimize_rules(rules);

std::cout << "(6/9) Grouping if statements by condition\n";
out_lines = zohrg::group_by_if_condition(out_lines);
std::cout << "(5/8) Creating rules file\n";
auto out_lines = create_rules_file(rules);

std::cout << "(7/9) Erasing unnecessary whitespace\n";
std::cout << "(6/8) Erasing unnecessary whitespace\n";
out_lines = zohrg::erase_unnecessary_whitespace(out_lines);

std::cout << "(8/9) Adding fixed rules\n";
fixed_lines.emplace_back("");
for (const auto &out_line : out_lines) {
fixed_lines.push_back(out_line);
}
std::cout << "(7/8) Adding fixed rules\n";
out_lines.emplace(out_lines.begin(), "");
out_lines.insert(out_lines.begin(), fixed_lines.begin(), fixed_lines.end());

std::cout << "(9/9) Writing " << fixed_lines.size() << " lines to output file\n\n";
zohrg::write_file(out_file, fixed_lines);
std::cout << "(8/8) Writing " << out_lines.size() << " lines to output file\n\n";
zohrg::write_file(out_file, out_lines);

std::cout << "Generator took " << static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now() - start_time).
count()) / 1000000.0 << " ms\n";
std::chrono::system_clock::now() - start_time).count()) / 1000000.0 << " ms\n";
std::cout << "Finished";

#ifdef PLATFORM_UNIX
Expand Down
164 changes: 17 additions & 147 deletions OpenHab2RulesGenerator/src/Optimizer.cpp
Original file line number Diff line number Diff line change
@@ -1,170 +1,40 @@
#include "Optimizer.h"
#include <iostream>
#include "StringUtils.h"

namespace zindach_openhab_rules_generator {

std::map<std::string, std::vector<size_t>> optimizable_rules(const std::vector<std::string> &lines) {
std::map<std::string, std::vector<size_t>> groups;

size_t when_line = line_index_equals(lines, "when", 0);
while (when_line != std::string::npos) {
const size_t then_line = line_index_equals(lines, "then", when_line + 1);
if (then_line - when_line == 2) {
groups[trim(lines[when_line + 1])].emplace_back(when_line + 1);
}

when_line = line_index_equals(lines, "when", then_line + 2);
std::vector<Rule> optimize_rules(std::vector<Rule> rules) {
std::map<std::string, std::vector<size_t>> rule_map;
for (size_t i = 0; i < rules.size(); ++i) {
rule_map[rules[i].condition].emplace_back(i);
}

for (auto iterator = groups.begin(); iterator != groups.end();) {
for (auto iterator = rule_map.begin(); iterator != rule_map.end();) {
if (iterator->second.size() <= 1) {
iterator = groups.erase(iterator);
iterator = rule_map.erase(iterator);
} else {
++iterator;
}
}
std::cout << "\toptimizing " << rule_map.size() << " rules\n";

return groups;
}

std::vector<std::string> group_by_condition(std::vector<std::string> lines) {
auto groups = optimizable_rules(lines);
std::cout << "\toptimizing " << groups.size() << " rules\n";

for (auto pair = groups.begin(); pair != groups.end(); pair = groups.erase(groups.begin())) {
const size_t first_rule_line_index = line_index_starts_with_reverse(lines, "rule", pair->second[0]);
for (auto &pair : rule_map) {
for (size_t i = 1; i < pair.second.size(); ++i) {
rules[pair.second[0]].rename();
rules[pair.second[0]].merge_rule(rules[pair.second[i]]);

lines[first_rule_line_index] = "rule \"Group " + erase_all(pair->first, {"*", "\"", "?", ":", "#"}) + "\"";

for (size_t i = 1; i < pair->second.size(); ++i) {
const size_t rule_line_index = line_index_starts_with_reverse(lines, "rule", pair->second[i]);
const size_t then_line_index = line_index_equals(lines, "then", rule_line_index);
const size_t end_line_index = line_index_equals(lines, "end", then_line_index);

const std::vector<std::string> additional_lines(lines.begin() + then_line_index + 1,
lines.begin() + end_line_index);

const size_t first_end_line_index = line_index_equals(lines, "end", first_rule_line_index);

lines.erase(lines.begin() + rule_line_index, lines.begin() + end_line_index + 1);
lines.insert(lines.begin() + first_end_line_index, additional_lines.begin(), additional_lines.end());

for (auto &values : groups) {
for (auto &value : values.second) {
if (value > first_end_line_index) {
value += additional_lines.size();
}
if (value > end_line_index) {
value -= end_line_index - rule_line_index + 1;
}
}
}
}
}

return lines;
}

std::vector<std::string> group_by_if_condition(const std::vector<std::string> &lines) {
std::vector<std::string> result = lines;
std::map<size_t, std::map<std::string, std::vector<size_t>>> if_conditions;

size_t then_line_idx = std::string::npos;
for (size_t i = 0; i < result.size(); ++i) {
std::string trim_line = trim(result[i]);
if (trim_line == "then") {
then_line_idx = i;
} else if (trim_line.find("if") == 0 && trim_line.find_last_of("{") == trim_line.size() - 1) {
if_conditions[then_line_idx][trim_line].emplace_back(i);
i = find_closing_brace(result, i);
}
}

auto rule_iterator = if_conditions.begin();
while (rule_iterator != if_conditions.end()) {
bool optimizable = false;

auto if_iterator = rule_iterator->second.begin();
while (if_iterator != rule_iterator->second.end()) {
if (if_iterator->second.size() <= 1) {
if_iterator = rule_iterator->second.erase(if_iterator);
} else {
optimizable = true;
++if_iterator;
}
}

if (!optimizable) {
rule_iterator = if_conditions.erase(rule_iterator);
} else {
++rule_iterator;
}
}
std::cout << "\toptimizing " << if_conditions.size() << " if statements\n";

rule_iterator = if_conditions.begin();
for (size_t k = 0; k < if_conditions.size(); ++k) {
auto if_iterator = rule_iterator->second.begin();
for (size_t l = 0; l < rule_iterator->second.size(); ++l) {
std::vector<std::string> additional_lines;
for (size_t i = 1; i < if_iterator->second.size(); ++i) {
const size_t end_if_line_idx = find_closing_brace(result, if_iterator->second[i]);

additional_lines.emplace_back("\t\tThread::sleep(2000)");
for (size_t j = if_iterator->second[i] + 1; j < end_if_line_idx; ++j) {
additional_lines.emplace_back(result[j]);
}

for (size_t j = 0; j < if_iterator->second.size(); ++j) {
if (if_iterator->second[j] > if_iterator->second[i]) {
if_iterator->second[j] -= end_if_line_idx - if_iterator->second[i] + 1;
}
}

auto iterator = result.begin();
advance(iterator, if_iterator->second[i]);
for (size_t j = if_iterator->second[i]; j <= end_if_line_idx; ++j) {
iterator = result.erase(iterator);
}
}

const size_t end_if_line_idx = find_closing_brace(result, if_iterator->second[0]);
auto iterator = result.begin();
advance(iterator, end_if_line_idx);
for (const auto &additional_line : additional_lines) {
iterator = result.emplace(iterator, additional_line);
++iterator;
}

const size_t removed_lines_count = if_iterator->second.size() - 1;
std::map<size_t, std::map<std::string, std::vector<size_t>>> new_if_conditions;
for (auto &rule_pair : if_conditions) {
if (rule_pair.first > end_if_line_idx) {
new_if_conditions[rule_pair.first - removed_lines_count] = rule_pair.second;
} else {
new_if_conditions[rule_pair.first] = rule_pair.second;
}
}
rules.erase(rules.begin() + pair.second[i], rules.begin() + pair.second[i] + 1);

for (auto &rule_pair : new_if_conditions) {
for (auto &if_condition_pair : rule_pair.second) {
for (auto &line_idx : if_condition_pair.second) {
if (line_idx > end_if_line_idx) {
line_idx -= removed_lines_count;
}
for (auto &rule : rule_map) {
for (auto &index : rule.second) {
if (index > pair.second[i]) {
--index;
}
}
}
if_conditions = new_if_conditions;
rule_iterator = if_conditions.begin();
advance(rule_iterator, k);
if_iterator = rule_iterator->second.begin();
advance(if_iterator, l + 1);
}
++rule_iterator;
}

return result;
return rules;
}
}
8 changes: 2 additions & 6 deletions OpenHab2RulesGenerator/src/Optimizer.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#pragma once
#include <map>
#include <string>
#include <vector>
#include "Rule.h"

namespace zindach_openhab_rules_generator {

std::map<std::string, std::vector<size_t>> optimizable_rules(const std::vector<std::string> &lines);
std::vector<std::string> group_by_condition(std::vector<std::string> lines);
std::vector<std::string> group_by_if_condition(const std::vector<std::string> &lines);
std::vector<Rule> optimize_rules(std::vector<Rule> rules);
}
13 changes: 5 additions & 8 deletions OpenHab2RulesGenerator/src/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace zindach_openhab_rules_generator {

std::vector<Rule> read_rules_from_file(const std::vector<std::string> &lines) {
std::vector<Rule> read_rules_from_file(const std::vector<std::string> &lines, std::map<std::string, Template> &templates) {
std::vector<Rule> result;
const size_t table_index = line_index_starts_with(lines, "Tabelle");

Expand All @@ -17,7 +17,7 @@ std::vector<Rule> read_rules_from_file(const std::vector<std::string> &lines) {
}

for (size_t i = table_index + 2; i < lines.size(); ++i) {
result.emplace_back(keys, lines[i]);
result.emplace_back(keys, lines[i], templates);
}

return result;
Expand All @@ -42,15 +42,12 @@ std::map<std::string, Template> read_templates_from_file(const std::vector<std::
return result;
}

std::vector<std::string> create_rules_file(std::vector<Rule> &rules, std::map<std::string, Template> &templates) {
std::vector<std::string> create_rules_file(std::vector<Rule> &rules) {
std::vector<std::string> result;

for (auto &rule : rules) {
const Template &temp = templates[rule.value_map["Aktion"]];
std::vector<std::string> template_lines = temp.replace(rule.value_map);

result.emplace_back("rule \"" + join_values(rule.value_map) + "\"");
result.insert(result.end(), template_lines.begin(), template_lines.end());
auto rule_lines = rule.to_string();
result.insert(result.end(), rule_lines.begin(), rule_lines.end());
}

return result;
Expand Down
4 changes: 2 additions & 2 deletions OpenHab2RulesGenerator/src/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace zindach_openhab_rules_generator {

std::vector<Rule> read_rules_from_file(const std::vector<std::string> &lines);
std::vector<Rule> read_rules_from_file(const std::vector<std::string> &lines, std::map<std::string, Template> &templates);
std::map<std::string, Template> read_templates_from_file(const std::vector<std::string> &lines);
std::vector<std::string> create_rules_file(std::vector<Rule> &rules, std::map<std::string, Template> &templates);
std::vector<std::string> create_rules_file(std::vector<Rule> &rules);
}
Loading

0 comments on commit 6d1218b

Please sign in to comment.