Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions Code/max/Containers/StateMachine/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@ namespace max {
namespace Containers {
namespace StateMachine {

template<typename... TransitionTypes>
template<typename NodeIndexType, typename... TransitionTypes>
class Node {
public:

constexpr explicit Node(std::tuple<TransitionTypes...> outbound_transitions) noexcept
: outbound_transitions_(std::move(outbound_transitions))
constexpr explicit Node(NodeIndexType this_node, std::tuple<TransitionTypes...> outbound_transitions) noexcept
: this_node_(std::move(this_node))
, outbound_transitions_(std::move(outbound_transitions))
{}

template<typename T>
constexpr std::optional<size_t> AttemptTransition(const T& input) noexcept {
constexpr std::optional<NodeIndexType> AttemptTransition(const T& input) noexcept {
auto transition_happened = false;
auto new_node_index = std::optional<size_t>{std::nullopt};
auto new_node_index = std::optional<NodeIndexType>{std::nullopt};

auto attempt_transition = [&transition_happened, &new_node_index, &input](auto&& arg) {
// TODO: I added .value_ to RangeMatcher because I couldn't get this line to work
//if constexpr (std::is_same_v<T, decltype(arg.matcher_)::parameter_type>) {
if constexpr (std::is_same_v<T, decltype(arg.matcher_.value_)>) {
if (!transition_happened) {
auto possible_new_node_index = arg.AttemptTransition(input);
auto possible_new_node_index = arg.template AttemptTransition<NodeIndexType>(input);
if (possible_new_node_index) {
transition_happened = true;
new_node_index = std::move(possible_new_node_index);
Expand All @@ -50,13 +51,14 @@ namespace StateMachine {
return new_node_index;
}

NodeIndexType this_node_;
std::tuple<TransitionTypes...> outbound_transitions_;

};

template<typename... TransitionTypes>
constexpr Node<TransitionTypes...> MakeNode(TransitionTypes... outbound_transitions) noexcept {
return Node{std::make_tuple(std::move(outbound_transitions) ...)};
template<typename NodeIndexType, typename... TransitionTypes>
constexpr Node<NodeIndexType, TransitionTypes...> MakeNode(NodeIndexType this_node, TransitionTypes... outbound_transitions) noexcept {
return Node{std::move(this_node), std::make_tuple(std::move(outbound_transitions) ...)};
}

} // namespace StateMachine
Expand Down
32 changes: 22 additions & 10 deletions Code/max/Containers/StateMachine/NodeTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,21 @@ namespace StateMachine {
return size_t{2};
};

auto range_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)};
auto range_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)
};

bool string_callback_called = false;
auto string_callback = [&string_callback_called](const std::string_view& /*input*/) {
string_callback_called = true;
return size_t{3};
};

auto string_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)};
auto string_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)
};

auto node = max::Containers::StateMachine::MakeNode(std::move(range_transition), std::move(string_transition));
auto node = max::Containers::StateMachine::MakeNode(size_t{0}, std::move(range_transition), std::move(string_transition));

auto new_node_index = node.AttemptTransition(uint32_t{1});

Expand All @@ -59,17 +63,21 @@ namespace StateMachine {
return 2;
};

auto range_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)};
auto range_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)
};

bool string_callback_called = false;
auto string_callback = [&string_callback_called](const std::string_view& /*input*/) {
string_callback_called = true;
return 3;
};

auto string_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)};
auto string_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)
};

auto node = max::Containers::StateMachine::MakeNode(std::move(range_transition), std::move(string_transition));
auto node = max::Containers::StateMachine::MakeNode(0, std::move(range_transition), std::move(string_transition));

auto new_node_index = node.AttemptTransition(uint32_t{2});

Expand All @@ -86,21 +94,25 @@ namespace StateMachine {
return 2;
};

auto range_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)};
auto range_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)
};

bool string_callback_called = false;
auto string_callback = [&string_callback_called](const std::string_view& /*input*/) {
string_callback_called = true;
return 3;
};

auto string_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)};
auto string_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)
};

auto node = max::Containers::StateMachine::MakeNode(std::move(range_transition), std::move(string_transition));
auto node = max::Containers::StateMachine::MakeNode(0, std::move(range_transition), std::move(string_transition));

auto new_node_index = node.AttemptTransition(std::string_view{"test"});

CurrentTest.MAX_TESTING_ASSERT( new_node_index == size_t{3} );
CurrentTest.MAX_TESTING_ASSERT( new_node_index == 3 );
CurrentTest.MAX_TESTING_ASSERT( !range_callback_called );
CurrentTest.MAX_TESTING_ASSERT( string_callback_called );
}
Expand Down
15 changes: 7 additions & 8 deletions Code/max/Containers/StateMachine/StateMachine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ namespace max {
namespace Containers {
namespace StateMachine {

template<typename... NodeTypes>
template<typename NodeIndexType, typename... NodeTypes>
class StateMachine {
public:

constexpr explicit StateMachine(std::tuple<NodeTypes...> nodes) noexcept
: nodes_(std::move(nodes))
, current_node_index_(0)
constexpr explicit StateMachine(NodeIndexType starting_node, std::tuple<NodeTypes...> nodes) noexcept
: current_node_index_(std::move(starting_node))
, nodes_(std::move(nodes))
{}

template<typename T>
constexpr void AttemptTransition(T input) noexcept {
auto transition_happened = false;
auto i = size_t{0};
auto attempt_transition = [this, &transition_happened, &i, &input](auto&& arg) {
if (!transition_happened && current_node_index_ == i++) {
auto attempt_transition = [this, &transition_happened, &input](auto&& arg) {
if (!transition_happened && current_node_index_ == arg.this_node_) {
auto possible_new_node_index = arg.AttemptTransition(input);
if (possible_new_node_index) {
transition_happened = true;
Expand All @@ -40,8 +39,8 @@ namespace StateMachine {
}, nodes_);
}

NodeIndexType current_node_index_;
std::tuple<NodeTypes...> nodes_;
size_t current_node_index_;

};

Expand Down
14 changes: 9 additions & 5 deletions Code/max/Containers/StateMachine/StateMachineTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,22 @@ namespace StateMachine {
range_callback_called = true;
return size_t{1};
};
auto range_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)};
auto node_0 = max::Containers::StateMachine::MakeNode(std::move(range_transition));
auto range_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(range_callback)
};
auto node_0 = max::Containers::StateMachine::MakeNode(size_t{0}, std::move(range_transition));

bool string_callback_called = false;
auto string_callback = [&string_callback_called](const std::string_view& /*input*/) {
string_callback_called = true;
return size_t{0};
};
auto string_transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)};
auto node_1 = max::Containers::StateMachine::MakeNode(std::move(string_transition));
auto string_transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::StringMatcher{std::string_view{"test"}}, std::move(string_callback)
};
auto node_1 = max::Containers::StateMachine::MakeNode(size_t{1}, std::move(string_transition));

auto state_machine = max::Containers::StateMachine::StateMachine{std::make_tuple(std::move(node_0), std::move(node_1))};
auto state_machine = max::Containers::StateMachine::StateMachine{size_t{0}, std::make_tuple(std::move(node_0), std::move(node_1))};

state_machine.AttemptTransition(uint32_t{1});

Expand Down
4 changes: 2 additions & 2 deletions Code/max/Containers/StateMachine/Transition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace StateMachine {
, callback_(std::move(callback))
{}

template<typename T>
constexpr std::optional<size_t> AttemptTransition(const T& input) noexcept {
template<typename NodeIndexType, typename T>
constexpr std::optional<NodeIndexType> AttemptTransition(const T& input) noexcept {
if (matcher_.DoesMatch(input)) {
return callback_(std::move(input));
}
Expand Down
12 changes: 8 additions & 4 deletions Code/max/Containers/StateMachine/TransitionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ namespace StateMachine {
return size_t{2};
};

auto transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(callback)};
auto transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(callback)
};

auto new_node_index = transition.AttemptTransition(uint32_t{2});
auto new_node_index = transition.AttemptTransition<size_t>(uint32_t{2});

// TODO: This should be constexpr, right??
//static_assert( !callback_called, "" );
Expand All @@ -48,9 +50,11 @@ namespace StateMachine {
return size_t{2};
};

auto transition = max::Containers::StateMachine::Transition{max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(callback)};
auto transition = max::Containers::StateMachine::Transition{
max::Containers::StateMachine::RangeMatcher<uint32_t>{0, 1}, std::move(callback)
};

auto new_node_index = transition.AttemptTransition(uint32_t{1});
auto new_node_index = transition.AttemptTransition<size_t>(uint32_t{1});

CurrentTest.MAX_TESTING_ASSERT( callback_called );
CurrentTest.MAX_TESTING_ASSERT( new_node_index == size_t{2} );
Expand Down
Loading