#include "turns/domain/turn_order.hpp" #include "turns/domain/participant.hpp" #include #include #include #include #include namespace turns::domain { namespace { auto constexpr comparator = [](auto lhs, auto rhs) { auto result = *lhs <=> *rhs; if (result == std::partial_ordering::equivalent || result == std::partial_ordering::unordered) { return 0; } else if (result == std::partial_ordering::less) { return 1; } return -1; }; auto constexpr equal_comparator = [](auto lhs, auto rhs) { return (lhs->get_name() == rhs->get_name()) && (lhs->get_priority() && rhs->get_priority()); }; } // namespace auto turn_order::create() -> Glib::RefPtr { return Glib::make_refptr_for_instance(new turn_order{}); } turn_order::turn_order() : Glib::ObjectBase{typeid(turn_order)} , m_model{Gio::ListStore::create()} , m_active_participant(*this, "active_participant", invalid_participant_index) , m_empty{*this, "empty", true} , m_has_next{*this, "has-next", false} , m_has_previous{*this, "has-previous", false} , m_running{*this, "running", false} , m_round{*this, "round", 0} { Glib::Binding::bind_property(m_model->property_n_items(), m_empty.get_proxy(), Glib::Binding::Flags::DEFAULT, [](auto n) { return n == 0; }); } /** Modifiers */ auto turn_order::add(Glib::ustring const & name, float priority, disposition disposition) -> void { auto participant = participant::create(name, priority, disposition); if (auto [found, index] = m_model->find(participant, equal_comparator); !found) { auto position = m_model->insert_sorted(participant, comparator); participant->property_priority().signal_changed().connect([this] { m_model->sort(comparator); }); if (m_active_participant != invalid_participant_index && position <= m_active_participant) { m_active_participant = m_active_participant + 1; } } } auto turn_order::clear() -> void { m_model->remove_all(); m_active_participant = invalid_participant_index; m_has_next = false; m_has_previous = false; m_running = false; } auto turn_order::next() -> void { m_active_participant = (m_active_participant + 1) % size(); if (!m_active_participant) { m_round = round() + 1; } m_has_previous = m_active_participant || m_round; } auto turn_order::previous() -> void { if (!m_has_previous) { return; } if (m_active_participant) { m_active_participant = m_active_participant - 1; } else if (m_round) { m_round = round() - 1; m_active_participant = size() - 1; } m_has_previous = m_active_participant || m_round; } auto turn_order::remove(unsigned int index) -> void { m_model->remove(index); if (empty()) { m_active_participant = invalid_participant_index; m_has_next = false; m_has_previous = false; m_running = false; } else if (m_active_participant != invalid_participant_index) { if (m_active_participant > size() - 1) { m_active_participant = size() - 1; } else if (index <= m_active_participant) { m_active_participant = m_active_participant - 1; } } } auto turn_order::reset() -> void { m_running = false; m_active_participant = 0; } auto turn_order::start() -> void { if (m_active_participant == invalid_participant_index) { m_active_participant = 0; } m_running = true; m_has_next = true; } auto turn_order::stop() -> void { m_running = false; m_has_next = false; } /** Querries */ auto turn_order::active_participant() const noexcept -> active_participant_type { return m_active_participant; } auto turn_order::empty() const noexcept -> bool { return m_empty; } auto turn_order::get(unsigned int index) const noexcept -> Glib::RefPtr { return m_model->get_item(index); } auto turn_order::list_model() -> Glib::RefPtr { return m_model; } auto turn_order::round() const noexcept -> round_type { return m_round; } auto turn_order::running() const noexcept -> running_type { return m_running; } auto turn_order::size() const noexcept -> unsigned int { return m_model->get_n_items(); } /** Properties */ auto turn_order::property_active_participant() const -> Glib::PropertyProxy_ReadOnly { return m_active_participant.get_proxy(); } auto turn_order::property_empty() const -> Glib::PropertyProxy_ReadOnly { return m_empty.get_proxy(); } auto turn_order::property_has_next() const -> Glib::PropertyProxy_ReadOnly { return m_has_next.get_proxy(); } auto turn_order::property_has_previous() const -> Glib::PropertyProxy_ReadOnly { return m_has_previous.get_proxy(); } auto turn_order::property_running() const -> Glib::PropertyProxy_ReadOnly { return m_running.get_proxy(); } auto turn_order::property_round() const -> Glib::PropertyProxy_ReadOnly { return m_round.get_proxy(); } } // namespace turns::domain