From 3f5499cebc06356ed99159be3fb9676292cf7b8b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 24 Jul 2024 10:44:13 +0200 Subject: turns: rename domain to core --- core/src/disposition.cpp | 25 ++++++ core/src/participant.cpp | 35 ++++++++ core/src/turn_order.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 core/src/disposition.cpp create mode 100644 core/src/participant.cpp create mode 100644 core/src/turn_order.cpp (limited to 'core/src') diff --git a/core/src/disposition.cpp b/core/src/disposition.cpp new file mode 100644 index 0000000..4eec33e --- /dev/null +++ b/core/src/disposition.cpp @@ -0,0 +1,25 @@ +#include "turns/core/disposition.hpp" + +#include + +namespace turns::core +{ + + auto presentation_name_for(disposition value) -> Glib::ustring + { + switch (value) + { + case disposition::neutral: + return _("Neutral"); + case disposition::friendly: + return _("Friendly"); + case disposition::hostile: + return _("Hostile"); + case disposition::secret: + return _("Secret"); + default: + return _("Unknown disposition value"); + } + } + +} // namespace turns::core \ No newline at end of file diff --git a/core/src/participant.cpp b/core/src/participant.cpp new file mode 100644 index 0000000..45b02bd --- /dev/null +++ b/core/src/participant.cpp @@ -0,0 +1,35 @@ +#include "turns/core/participant.hpp" + +#include +#include + +#include +#include + +namespace turns::core +{ + auto participant::create(Glib::ustring name, float priority, core::disposition disposition) -> Glib::RefPtr + { + return Glib::make_refptr_for_instance(new participant{name, priority, disposition}); + } + + participant::participant() + : Glib::ObjectBase{typeid(participant)} + , Glib::Object{} + { + } + + participant::participant(Glib::ustring name, float priority, core::disposition disposition) + : participant() + { + m_name = name; + m_priority = priority; + m_disposition = disposition; + } + + auto participant::operator<=>(participant const & other) const noexcept -> std::partial_ordering + { + return m_priority <=> other.m_priority; + } + +} // namespace turns::core \ No newline at end of file diff --git a/core/src/turn_order.cpp b/core/src/turn_order.cpp new file mode 100644 index 0000000..ae3511e --- /dev/null +++ b/core/src/turn_order.cpp @@ -0,0 +1,225 @@ +#include "turns/core/turn_order.hpp" + +#include "turns/core/participant.hpp" + +#include +#include +#include +#include + +#include + +namespace turns::core +{ + + namespace + { + auto constexpr comparator = [](auto lhs, auto rhs) { + return *lhs > *rhs; + }; + + auto constexpr equal_comparator = [](auto lhs, auto rhs) { + return (lhs->get_name() == rhs->get_name()) && (lhs->get_priority() && rhs->get_priority()); + }; + } // namespace + + /** Construction */ + + turn_order::turn_order() + : Glib::ObjectBase{typeid(turn_order)} + , Gio::ListModel{} + { + } + + auto turn_order::create() -> Glib::RefPtr + { + return Glib::make_refptr_for_instance(new turn_order{}); + } + + /** Queries */ + + auto turn_order::is_empty() const -> Glib::PropertyProxy_ReadOnly + { + return m_is_empty.get_proxy(); + } + + auto turn_order::has_next() const -> Glib::PropertyProxy_ReadOnly + { + return m_has_next.get_proxy(); + } + + auto turn_order::has_previous() const -> Glib::PropertyProxy_ReadOnly + { + return m_has_previous.get_proxy(); + } + + auto turn_order::is_running() const -> Glib::PropertyProxy_ReadOnly + { + return m_is_running.get_proxy(); + } + + auto turn_order::round_number() const -> Glib::PropertyProxy_ReadOnly + { + return m_round_number.get_proxy(); + } + + /** Modifiers */ + + auto turn_order::add(Glib::ustring const & name, float priority, disposition disposition) -> void + { + auto entry = participant::create(name, priority, disposition); + entry->priority().signal_changed().connect(sigc::bind(sigc::mem_fun(*this, &turn_order::handle_priority_changed), entry)); + auto position = std::distance(m_data.cbegin(), insert(entry)); + items_changed(position, 0, 1); + + if (get_n_items() == 1) + { + m_is_empty = false; + m_has_next = true; + } + } + + auto turn_order::clear() -> void + { + m_is_running = false; + m_is_empty = true; + m_has_next = false; + m_has_previous = false; + m_active.reset(); + m_round_number = invalid_round_number; + + auto old_size = get_n_items(); + m_data.clear(); + items_changed(0, old_size, 0); + } + + auto turn_order::next() -> void + { + auto old_active = *m_active; + m_active = m_active.transform([this](auto index) { return (index + 1) % get_n_items(); }); + + m_has_previous = true; + m_data[old_active]->is_active() = false; + m_data[*m_active]->is_active() = true; + + if (m_active == 0) + { + m_round_number = m_round_number + 1; + } + } + + auto turn_order::previous() -> void + { + if (!(m_has_previous && m_is_running)) + { + return; + } + + auto old_active = *m_active; + m_active = m_active.transform([this](auto index) { return index ? index - 1 : get_n_items() - 1; }); + + m_has_previous = m_round_number > 0 || m_active > 0; + m_data[old_active]->is_active() = false; + m_data[*m_active]->is_active() = true; + + if (m_active == 0 && m_round_number > 0) + { + m_round_number = m_round_number - 1; + } + } + + auto turn_order::remove(unsigned index) -> void + { + if (index >= get_n_items()) + { + return; + } + + auto position = m_data.begin() + index; + m_data.erase(position); + items_changed(index, 1, 0); + if (get_n_items() == 0) + { + m_is_empty = true; + m_is_running = false; + m_has_next = false; + } + } + + auto turn_order::start() -> void + { + if (!m_active) + { + m_active = 0; + m_data[*m_active]->is_active() = true; + } + if (m_round_number == invalid_round_number) + { + m_round_number = 0; + } + m_is_running = true; + } + + auto turn_order::stop() -> void + { + m_is_running = false; + } + + /** ListModel implementation */ + + auto turn_order::get_item_type_vfunc() -> GType + { + return participant::get_type(); + } + + auto turn_order::get_n_items_vfunc() -> unsigned + { + return m_data.size(); + } + + auto turn_order::get_item_vfunc(unsigned position) -> void * + { + if (position >= get_n_items()) + { + return nullptr; + } + auto item = m_data[position]; + item->reference(); + return item->gobj(); + } + + /** Signal handlers */ + + auto turn_order::handle_priority_changed(value_type entry) -> void + { + auto original_position = find(entry); + auto original_index = distance(m_data.cbegin(), original_position); + auto target_position = std::ranges::upper_bound(m_data, entry, comparator); + if (original_position == target_position) + { + return; + } + + m_data.erase(original_position); + auto inserted_position = insert(entry); + items_changed(0, get_n_items(), get_n_items()); + if (m_active == original_index) + { + m_active = distance(m_data.cbegin(), inserted_position); + m_has_previous = m_round_number > 0 || m_active > 0; + } + } + + /** Data management */ + + auto turn_order::find(value_type entry) const -> const_iterator + { + return std::ranges::find(m_data, entry); + } + + auto turn_order::insert(value_type entry) -> const_iterator + { + return m_data.insert(std::ranges::upper_bound(m_data, entry, comparator), entry); + } + +} // namespace turns::core \ No newline at end of file -- cgit v1.2.3