diff --git a/src/controller/evento_service.cpp b/src/controller/evento_service.cpp index 8daad66..6fa2b32 100644 --- a/src/controller/evento_service.cpp +++ b/src/controller/evento_service.cpp @@ -21,12 +21,7 @@ #include "undertaking_evento_model.h" #include "user_helper.h" -#include - -#include #include -#include -#include void EventoService::load_Plaza() { std::array, 2> tasks = { @@ -462,27 +457,5 @@ EventoBrief::EventoBrief(const DTO_Evento& src) EventoBlock::EventoBlock(const DTO_Evento& src, const std::set& permitted) : id(src.id), title(src.title), gmtEventStart(src.gmtEventStart), gmtEventEnd(src.gmtEventEnd), editable(permitted.count(src.id)) { - if (gmtEventStart.date() == gmtEventEnd.date()) { - auto time = gmtEventStart.time(); - if (time.hour() < 8) - start.ahead = 1; - else - start.major = (time.hour() - 8); - if (time.hour() != 23) - start.fraction = (time.minute() * 60 + time.second()) / 450; - time = gmtEventEnd.time(); - if (time.hour() >= 8) - end.major = (time.hour() - 8); - if (time.hour() == 23 && time != QTime(23, 0)) - end.ahead = 1; - else - end.fraction = (time.minute() * 60 + time.second()) / 450; - column_or_flag = gmtEventStart.date().dayOfWeek() - 1; - } else { - if (getMonday(gmtEventStart.date()) == getMonday(gmtEventEnd.date())) { - column_or_flag = -1; - start.major = gmtEventStart.date().dayOfWeek() - 1; - end.major = gmtEventEnd.date().dayOfWeek(); - } - } + init(); } diff --git a/src/domain/entity/evento_block.h b/src/domain/entity/evento_block.h index 1322f13..68c75c5 100644 --- a/src/domain/entity/evento_block.h +++ b/src/domain/entity/evento_block.h @@ -7,39 +7,45 @@ struct DTO_Evento; -struct TimePoint { - uint8_t fraction : 3; - uint8_t major : 4; - uint8_t ahead : 1; +struct IEEE_Float { + uint32_t m : 23; + uint32_t e : 8; + uint32_t sign : 1; - operator uint8_t() { - return *reinterpret_cast(this); + operator float() { + return *reinterpret_cast(this); } +}; - TimePoint() { - *(uint8_t*)this = 0; +template +struct FixedPoint { + uint8_t fraction : 7 - major_bits; + uint8_t major : major_bits; + uint8_t out_of_range : 1; + + operator uint8_t() const { + return *reinterpret_cast(this); } - struct IEEE_Float { - uint32_t m : 23; - uint32_t e : 8; - uint32_t sign : 1; + template + operator FixedPoint() const { + return *reinterpret_cast>*>( + this); + } - operator float() { - return *reinterpret_cast(this); - } - }; + FixedPoint() { + *(uint8_t*)this = 0; + } - static inline float to_float(TimePoint t) { + static inline float to_float(FixedPoint t) { constexpr uint32_t M_OPRAND = 0b100'00000'00000'00000'00000; static_assert(QSysInfo::ByteOrder == QSysInfo::LittleEndian, "Big Endian Untested!"); - if (t.ahead) + if (t.out_of_range) return t.major ? t.major + 0.5 : -0.5; if (!t.major && !t.fraction) return 0; - t.ahead = 0; IEEE_Float result; - result.e = 127 + 20; // 24 - bitsize of (major) + result.e = 127 + 24 - major_bits; // 24 - bitsize of (major) result.m = t; result.sign = 0; while (!(result.m & M_OPRAND)) { @@ -52,14 +58,19 @@ struct TimePoint { } }; +inline QDate getMonday(QDate date) { + auto day_of_week = date.dayOfWeek() - 1; + return date.addDays(-day_of_week); +} + struct EventoBlock { EventoID id = -1; QString title; QDateTime gmtEventStart; QDateTime gmtEventEnd; int8_t column_or_flag = -2; - TimePoint start; // index: 8:00 -> 0 - TimePoint end; // index: 23:00 -> 15 + FixedPoint<> start; + FixedPoint<> end; bool editable = false; int depth = -1; @@ -70,20 +81,42 @@ struct EventoBlock { if (column_or_flag >= -1) return; if (gmtEventStart.date() < monday) - start.ahead = 1; + start.out_of_range = 1; else start.major = gmtEventStart.date().dayOfWeek() - 1; if (gmtEventEnd.date() > monday.addDays(6)) { - end.ahead = 1; + end.out_of_range = 1; end.major = 7; } else end.major = gmtEventEnd.date().dayOfWeek(); } -}; -static inline QDate getMonday(QDate date) { - auto day_of_week = date.dayOfWeek() - 1; - return date.addDays(-day_of_week); -} +private: + void init() { + if (gmtEventStart.date() == gmtEventEnd.date()) { + auto time = gmtEventStart.time(); + if (time.hour() < 8) + start.out_of_range = 1; + else + start.major = time.hour() - 8; + if (time.hour() != 23) + start.fraction = (time.minute() * 60 + time.second()) / 450; + time = gmtEventEnd.time(); + if (time.hour() > 8) + end.major = time.hour() - 8; + if (time.hour() == 23 && time != QTime(23, 0)) + end.out_of_range = 1; + if (time.hour() >= 8) + end.fraction = (time.minute() * 60 + time.second()) / 450; + column_or_flag = gmtEventStart.date().dayOfWeek() - 1; + } else { + if (getMonday(gmtEventStart.date()) == getMonday(gmtEventEnd.date())) { + column_or_flag = -1; + start.major = gmtEventStart.date().dayOfWeek() - 1; + end.major = gmtEventEnd.date().dayOfWeek(); + } + } + } +}; #endif // EVENTOBLOCK_H diff --git a/src/domain/model/evento_block_model.cpp b/src/domain/model/evento_block_model.cpp index 2814e75..7afd2cf 100644 --- a/src/domain/model/evento_block_model.cpp +++ b/src/domain/model/evento_block_model.cpp @@ -29,16 +29,19 @@ QVariant EventoBlockModel::data(const QModelIndex& index, int role) const { case Role::Column: return element.column_or_flag; case Role::Start: - return TimePoint::to_float(element.start); + return FixedPoint<>::to_float(element.start); case Role::End: - return TimePoint::to_float(element.end); + return FixedPoint<>::to_float(element.end); case Role::Editable: return element.editable; case Role::Depth: return element.depth; case Role::DepthMax: - return element.column_or_flag < 0 ? all_day_line_max - : z_map[element.column_or_flag][element.start.major]; + if (element.column_or_flag < 0) + return all_day_line_max; + if (element.start.out_of_range) + return z_map[element.column_or_flag][31]; + return z_map[element.column_or_flag][static_cast>(element.start).major]; } return QVariant(); @@ -89,18 +92,20 @@ void EventoBlockModel::arrange_pipeline(QDate monday) { std::vector all_day; std::vector all_day_map; std::array, 7> z_map_layout = {}; - std::array, 7> z_map_rel = {}; - auto max = m_data.size(); + std::array, 7> z_map_rel = {}; + z_map = {}; for (auto& i : z_map_layout) i.push_back(INIT); bucket.emplace_back(); // Generate Depth Infos + auto max = m_data.size(); for (auto i = 0; i < max; ++i) { auto& element = m_data[i]; element.fresh(monday); if (element.column_or_flag < 0) { + // Multi-day ALL_DAY_MAP_FLAG flag = NUL; for (auto index = element.start.major; index <= element.end.major; ++index) flag = ALL_DAY_MAP_FLAG(flag | all_day_dict[index]); @@ -118,20 +123,28 @@ void EventoBlockModel::arrange_pipeline(QDate monday) { } all_day.push_back(i); } else { - auto end = element.end.major; - if (!end) { - element.depth = 0; - continue; - } - if (!element.end.fraction) - end--; + // Normal + auto column = element.column_or_flag; + auto start = static_cast>(element.start); + auto end = static_cast>(element.end); + auto end_max = end.major; + if (end_max && !end.fraction) + end_max--; Z_MAP_FLAG flag = INIT; - for (auto index = element.start.major; index <= end; ++index) + for (auto index = start.major; index <= end_max; ++index) flag = Z_MAP_FLAG(flag | dict[index]); - auto& rel = z_map_rel[element.column_or_flag]; - for (auto index = element.start.major; index <= end; ++index) + if (end.out_of_range) + flag = Z_MAP_FLAG(flag | After_PM_11); + if (start.out_of_range) + flag = Z_MAP_FLAG(flag | Before_AM_8); + auto& rel = z_map_rel[column]; + for (auto index = start.major; index <= end_max; ++index) rel[index] = Z_MAP_FLAG(rel[index] | flag); - auto& layout = z_map_layout[element.column_or_flag]; + if (end.out_of_range) + rel[30] = Z_MAP_FLAG(rel[30] | flag); + if (start.out_of_range) + rel[31] = Z_MAP_FLAG(rel[31] | flag); + auto& layout = z_map_layout[column]; auto max = layout.size(); std::size_t j; for (j = 0; j < max; j++) @@ -145,10 +158,14 @@ void EventoBlockModel::arrange_pipeline(QDate monday) { element.depth = max; bucket.emplace_back(); } - auto& col = z_map[element.column_or_flag]; - for (auto index = element.start.major; index <= end; ++index) + auto& col = z_map[column]; + for (auto index = start.major; index <= end_max; ++index) if (col[index] < element.depth) col[index] = element.depth; + if (end.out_of_range) + col[30] = element.depth; + if (start.out_of_range) + col[31] = element.depth; bucket[element.depth].push_back(i); } } @@ -162,21 +179,21 @@ void EventoBlockModel::arrange_pipeline(QDate monday) { this->setProperty("all_day_line_num", (quint64)all_day_map.size()); // update z_map for (auto col = 0; col < 7; col++) { + auto& map = z_map[col]; Z_MAP_FLAG processed = INIT; Z_MAP_FLAG current_set; int max; - for (auto i = 0; i < 15; i++) + for (auto i = 0; i < 32; i++) if (!(processed & dict[i])) { current_set = dict[i]; - max = z_map[col][i]; + max = map[i]; auto rel = z_map_rel[col][i]; auto will_visit = Z_MAP_FLAG(rel & (rel ^ current_set)); if (!will_visit) { processed = Z_MAP_FLAG(processed | current_set); continue; } - int count = 14; - auto& map = z_map[col]; + int count = 31; while (will_visit) { if (will_visit & dict[count]) { if (max < map[count]) @@ -186,12 +203,12 @@ void EventoBlockModel::arrange_pipeline(QDate monday) { will_visit = Z_MAP_FLAG(rel & (rel ^ current_set)); } if (!count) - count = 14; + count = 31; else count--; } - for (count = 0; count < 15; count++) - if (processed & dict[count]) + for (count = 0; count < 32; count++) + if (current_set & dict[count]) map[count] = max; processed = Z_MAP_FLAG(processed | current_set); } diff --git a/src/domain/model/evento_block_model.h b/src/domain/model/evento_block_model.h index 6c0a0cf..b7e39da 100644 --- a/src/domain/model/evento_block_model.h +++ b/src/domain/model/evento_block_model.h @@ -43,7 +43,7 @@ class EventoBlockModel : public QAbstractListModel { std::vector m_data; std::vector pipeline; - std::array, 7> z_map = {}; + std::array, 7> z_map = {}; int all_day_line_max; enum ALL_DAY_MAP_FLAG : uint8_t { @@ -58,27 +58,46 @@ class EventoBlockModel : public QAbstractListModel { }; static constexpr const ALL_DAY_MAP_FLAG all_day_dict[] = {MON, TUE, WED, THU, FRI, SAT, SUN}; - enum Z_MAP_FLAG : uint16_t { - AM_8 = 1 << 0, - AM_9 = 1 << 1, - AM_10 = 1 << 2, - AM_11 = 1 << 3, - AM_12 = 1 << 4, - PM_1 = 1 << 5, - PM_2 = 1 << 6, - PM_3 = 1 << 7, - PM_4 = 1 << 8, - PM_5 = 1 << 9, - PM_6 = 1 << 10, - PM_7 = 1 << 11, - PM_8 = 1 << 12, - PM_9 = 1 << 13, - PM_10 = 1 << 14, + enum Z_MAP_FLAG : uint32_t { + AM_8 = 1u << 0, + AM_8_30 = 1u << 1, + AM_9 = 1u << 2, + AM_9_30 = 1u << 3, + AM_10 = 1u << 4, + AM_10_30 = 1u << 5, + AM_11 = 1u << 6, + AM_11_30 = 1u << 7, + AM_12 = 1u << 8, + AM_12_30 = 1u << 9, + PM_1 = 1u << 10, + PM_1_30 = 1u << 11, + PM_2 = 1u << 12, + PM_2_30 = 1u << 13, + PM_3 = 1u << 14, + PM_3_30 = 1u << 15, + PM_4 = 1u << 16, + PM_4_30 = 1u << 17, + PM_5 = 1u << 18, + PM_5_30 = 1u << 19, + PM_6 = 1u << 20, + PM_6_30 = 1u << 21, + PM_7 = 1u << 22, + PM_7_30 = 1u << 23, + PM_8 = 1u << 24, + PM_8_30 = 1u << 25, + PM_9 = 1u << 26, + PM_9_30 = 1u << 27, + PM_10 = 1u << 28, + PM_10_30 = 1u << 29, + After_PM_11 = 1u << 30, + Before_AM_8 = 1u << 31, INIT = 0 }; static constexpr const Z_MAP_FLAG dict[] = { - AM_8, AM_9, AM_10, AM_11, AM_12, PM_1, PM_2, PM_3, - PM_4, PM_5, PM_6, PM_7, PM_8, PM_9, PM_10, + AM_8, AM_8_30, AM_9, AM_9_30, AM_10, AM_10_30, AM_11, AM_11_30, + AM_12, AM_12_30, PM_1, PM_1_30, PM_2, PM_2_30, PM_3, PM_3_30, + PM_4, PM_4_30, PM_5, PM_5_30, PM_6, PM_6_30, PM_7, PM_7_30, + PM_8, PM_8_30, PM_9, PM_9_30, PM_10, PM_10_30, After_PM_11, Before_AM_8, }; private: