#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* A DEFAULT IMPLEMENTATION OF PROHIBITED ZONES HOLDER */ #include "mcc_mount_concepts.h" namespace mcc { template class MccPZoneContainer : public traits::MccPZoneAbstractContainer { public: typedef TelemetryDataT telemetry_data_t; // a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted typedef std::chrono::duration duration_t; // seconds as floating-point number // adaptor class for prohibited zones struct MccPZoneWrapper { using duration_t = MccPZoneContainer::duration_t; static constexpr duration_t infiniteDuration{std::numeric_limits::infinity()}; static constexpr duration_t zeroDuration{0.0}; typedef std::function pz_inzone_func_t; typedef std::function pz_timeto_func_t; typedef std::function pz_timefrom_func_t; MccCoordPairKind coordPairKind; const std::function name; pz_inzone_func_t inZone; pz_timeto_func_t timeTo; pz_timefrom_func_t timeFrom; MccPZoneWrapper(MccPZoneWrapper&& other) : inZone(std::move(other.inZone)), timeTo(std::move(other.timeTo)), timeFrom(std::move(other.timeFrom)) {}; MccPZoneWrapper& operator=(MccPZoneWrapper&& other) { if (this != &other) { inZone = std::move(other.inZone); timeTo = std::move(other.timeTo); timeFrom = std::move(other.timeFrom); } return *this; }; MccPZoneWrapper() = default; }; MccPZoneContainer() = default; virtual ~MccPZoneContainer() = default; size_t pzSize() const { return _pzWrapperVec.size(); } // add zone/zones template ZT, traits::mcc_prohibited_zone_c... ZTs> size_t pzAddZone(ZT zone, ZTs... zones) { auto zone_ptr = std::make_shared(std::move(zone)); using d_t = typename MccPZoneWrapper::duration_t; _pzWrapperVec.emplace_back( {.coordPairKind = ZT::zoneCoordPairKind, .name = [zone_ptr]() { return std::format("{}", zone_ptr->name()); }, .inZone = [zone_ptr](const telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); }, .timeTo = [zone_ptr](const telemetry_data_t& tmry_data) { auto d = zone_ptr->timeTo(tmry_data); if constexpr (std::same_as) { return d; } else { if (d == ZT::infiniteDuration) { return MccPZoneWrapper::infiniteDuration; } else if (d == ZT::zeroDuration) { return MccPZoneWrapper::zeroDuration; } return std::chrono::duration_cast(d); } }, .timeFrom = [zone_ptr](const telemetry_data_t& tmry_data) { auto d = zone_ptr->timeFrom(tmry_data); if constexpr (std::same_as) { return d; } else { if (d == ZT::infiniteDuration) { return MccPZoneWrapper::infiniteDuration; } else if (d == ZT::zeroDuration) { return MccPZoneWrapper::zeroDuration; } return std::chrono::duration_cast(d); } }}); if constexpr (sizeof...(ZTs)) { pzAddZone(std::move(zones)...); } return _pzWrapperVec.size(); } void pzClearZones() { // stop mount here?!! _pzWrapperVec.clear(); } // visitors template FT> auto pzForeachZone(FT&& func) requires std::same_as, void> { for (auto& wr : _pzWrapperVec) { std::forward(func)(wr); } } template FT, std::ranges::output_range> ResT = std::vector>> auto pzForeachZone(FT&& func) requires(!std::same_as, void>) { ResT result; for (auto& wr : _pzWrapperVec) { std::back_inserter(result) = std::forward(func)(wr); } return result; } template RT> bool pzInZone(const telemetry_data_t& tdata, RT& result) { bool in_zone = false; auto const p_tdata = &tdata; result = pzForeachZone([&in_zone, p_tdata](auto& wr) { bool r = wr.inZone(*p_tdata); in_zone |= r; return r; }); return in_zone; } template RT> bool pzInZone(traits::mcc_celestial_point_c auto const& target, RT& result) { bool in_zone = false; auto const p_target = ⌖ result = pzForeachZone([&in_zone, p_target](auto& wr) { bool r = wr.inZone(*p_target); in_zone |= r; return r; }); return in_zone; } protected: std::vector _pzWrapperVec{}; }; class PZC { protected: struct point_t { typedef std::chrono::system_clock::time_point time_point_t; typedef double coord_t; time_point_t time_point; MccCoordPairKind coordPairKind; coord_t x, y; }; static_assert(traits::mcc_celestial_point_c); template static inline std::unordered_map>> _zones{}; std::vector> _clearFunc{}; // template // static inline std::unordered_map(const CPT&)>> _inZoneFunc = [](){ // }; // template // static inline std::function(const PZC*, const CPT&)> _inZoneFunc = // [](const PZC* cont, const CPT& cp) { // std::vector res; // for (ZT& zone : _zones[cont]) { // res.emplace_back(zone.inZone(cp)); // } // return res; // }; std::vector> _inZoneFunc; public: template size_t addZone(ZT zone) { auto sptr = std::make_shared(std::move(zone)); _zones[this].emplace_back(sptr); if (_zones[this].size() == 1) { _clearFunc.emplace_back([this]() { _zones[this].clear(); }); _inZoneFunc.emplace_back([sptr](const point_t& cp) { return sptr->inZone(cp); }); } } template RT> bool inZone(const CPT& cp, RT& res) { using tp_t = typename point_t::time_point_t; using cp_tp_t = typename CPT::time_point_t; bool in_zone = false, r; point_t pt{.coordPairKind = cp.coordPairKind, .x = cp.x, .y = cp.y}; if constexpr (traits::mcc_systime_c) { pt.time_point = std::chrono::time_point_cast(cp.time_point); } else if constexpr (std::is_arithmetic_v) { pt.time_point = tp_t{std::chrono::duration(static_cast(cp.time_point))}; } else { static_assert(false, "INVALID TYPE!"); } res = RT(); for (auto& func : _inZoneFunc) { r = func(pt); in_zone |= r; std::back_inserter(res) = r; } return in_zone; } }; } // namespace mcc