diff --git a/src/include/data.h b/src/include/data.h index 999facd..991b05d 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -16,9 +16,16 @@ struct StationNameData { }; static_assert(sizeof(StationNameData) == 4000); struct TicketPriceData { + char trainID[21]; uint32_t price[99]; }; +struct AdditionalTrainInfo { + char trainID[21]; + int price; + int seats; +}; + struct CoreTrainData { char trainID[21]; uint8_t stationNum; diff --git a/src/include/stop_register.hpp b/src/include/stop_register.hpp index dc48f75..4ea1826 100644 --- a/src/include/stop_register.hpp +++ b/src/include/stop_register.hpp @@ -1,14 +1,26 @@ #ifndef STOP_REGISTER_HPP #define STOP_REGISTER_HPP +#include #include #include "basic_defs.h" #include "data.h" #include "storage/bpt.hpp" #include "storage/buffer_pool_manager.h" #include "storage/driver.h" -typedef std::pair stop_register_t; // The first is station hash, the second is train hash +struct stop_register_t { + hash_t station_ID_hash; + hash_t train_ID_hash; + uint16_t type : 1; + uint16_t startTime : 12; +}; +inline bool operator<(const stop_register_t &A, const stop_register_t &B) { + if (A.station_ID_hash != B.station_ID_hash) return A.station_ID_hash < B.station_ID_hash; + if (A.train_ID_hash != B.train_ID_hash) return A.train_ID_hash < B.train_ID_hash; + if (A.type != B.type) return A.type < B.type; + return A.startTime < B.startTime; +} struct MinimalTrainRecord { - uint16_t saleDate_beg : 7, saleDate_end : 7, vis_time_offset : 13, type : 1; + uint16_t saleDate_beg : 8, saleDate_end : 8, vis_time_offset : 14; }; static_assert(sizeof(MinimalTrainRecord) == sizeof(default_numeric_index_t)); @@ -20,6 +32,12 @@ class StopRegister : public DataDriverBase { BPlusTreeIndexer> *bpt_indexer; public: + struct DirectTrainInfo { + hash_t train_ID_hash; + int actual_start_date; + int leave_time_stamp; + int arrive_time_stamp; + }; // for satety, all the copy/move operations are deleted, please manage it using pointer StopRegister &operator=(const StopRegister &) = delete; StopRegister(const StopRegister &) = delete; @@ -54,30 +72,66 @@ class StopRegister : public DataDriverBase { bpt_indexer->Flush(); } inline void AddStopInfo(hash_t station_hash, hash_t train_hash, uint16_t true_saleDate_beg, - uint16_t true_saleDate_end, uint16_t arrive_time_offset, uint16_t leave_time_offset) { + uint16_t true_saleDate_end, uint16_t startTime, uint16_t arrive_time_offset, + uint16_t leave_time_offset) { MinimalTrainRecord record_arrive, record_leave; const static int June_1st_2024 = 152; record_arrive.saleDate_beg = true_saleDate_beg - June_1st_2024; record_arrive.saleDate_end = true_saleDate_end - June_1st_2024; record_arrive.vis_time_offset = arrive_time_offset; - record_arrive.type = 0; record_leave.saleDate_beg = true_saleDate_beg - June_1st_2024; record_leave.saleDate_end = true_saleDate_end - June_1st_2024; record_leave.vis_time_offset = leave_time_offset; - record_leave.type = 1; if (arrive_time_offset != uint16_t(-1)) - bpt_indexer->Put({station_hash, train_hash}, *reinterpret_cast(&record_arrive)); + bpt_indexer->Put({station_hash, train_hash, 0, startTime}, + *reinterpret_cast(&record_arrive)); if (leave_time_offset != uint16_t(-1)) - bpt_indexer->Put({station_hash, train_hash}, *reinterpret_cast(&record_leave)); + bpt_indexer->Put({station_hash, train_hash, 1, startTime}, + *reinterpret_cast(&record_leave)); } - inline void GetShareItems(std::vector &A, std::vector &B, std::vector &res) { - // TODO - } - inline void QueryDirectTrains(uint32_t date, hash_t from_station_ID, hash_t to_station_ID, std::vector &res) { - std::vector valid_trains_pass_from, valid_trains_pass_to; - res.clear(); - // TODO - GetShareItems(valid_trains_pass_from, valid_trains_pass_to, res); + inline void QueryDirectTrains(uint32_t date, hash_t from_station_ID, hash_t to_station_ID, + std::vector &res) { + const static int June_1st_2024 = 152; + auto it_from = bpt_indexer->lower_bound_const({from_station_ID, 0}); + auto it_to = bpt_indexer->lower_bound_const({to_station_ID, 0}); + while (it_from != bpt_indexer->end_const()) { + const auto &key_from = it_from.GetKey(); + const auto &value_from = it_from.GetValue(); + if (key_from.station_ID_hash != from_station_ID) break; + if (key_from.type != 1) { + ++it_from; + continue; + } + int true_saleDate_beg = (*reinterpret_cast(&value_from)).saleDate_beg + June_1st_2024; + int true_saleDate_end = (*reinterpret_cast(&value_from)).saleDate_end + June_1st_2024; + int leave_time_offset = (*reinterpret_cast(&value_from)).vis_time_offset; + int startTime = key_from.startTime; + int actual_time = startTime + leave_time_offset; + int delta_days = actual_time / 1440; + if (date - delta_days < true_saleDate_beg || date - delta_days > true_saleDate_end) continue; + StopRegister::DirectTrainInfo entry; + entry.train_ID_hash = key_from.train_ID_hash; + entry.actual_start_date = date - delta_days; + entry.leave_time_stamp = true_saleDate_beg * 1440 + actual_time; + while (it_to != bpt_indexer->end_const()) { + const auto &key_to = it_to.GetKey(); + const auto &value_to = it_to.GetValue(); + if (key_to.station_ID_hash != to_station_ID) break; + if (key_to.type != 0) { + ++it_to; + continue; + } + if (key_to.train_ID_hash > key_from.train_ID_hash) break; + if (key_to.train_ID_hash == key_from.train_ID_hash) { + entry.arrive_time_stamp = true_saleDate_beg * 1440 + startTime + + (*reinterpret_cast(&value_to)).vis_time_offset; + ++it_to; + break; + } + ++it_to; + } + ++it_from; + } } }; diff --git a/src/train_system.cpp b/src/train_system.cpp index 2b0b4d6..6222904 100644 --- a/src/train_system.cpp +++ b/src/train_system.cpp @@ -140,6 +140,7 @@ std::string TicketSystemEngine::AddTrain(const std::string &command) { } TicketPriceData ticket_price_data; for (int i = 0; i < stationNum - 1; i++) ticket_price_data.price[i] = prices[i]; + strcpy(ticket_price_data.trainID, trainID.c_str()); ticket_price_data_storage.Put(train_id_hash, ticket_price_data); CoreTrainData core_train_data; core_train_data.is_released = 0; @@ -260,7 +261,8 @@ std::string TicketSystemEngine::ReleaseTrain(const std::string &command) { leave_time_offset = vis_time_offset; } stop_register.AddStopInfo(core_train_data.stations_hash[i], train_id_hash, core_train_data.saleDate_beg, - core_train_data.saleDate_end, arrive_time_offset, leave_time_offset); + core_train_data.saleDate_end, core_train_data.startTime, arrive_time_offset, + leave_time_offset); } response_stream << '[' << command_id << "] 0"; return response_stream.str(); diff --git a/src/transaction_system.cpp b/src/transaction_system.cpp index c109a5a..2d00b90 100644 --- a/src/transaction_system.cpp +++ b/src/transaction_system.cpp @@ -48,6 +48,14 @@ std::string TicketSystemEngine::QueryTicket(const std::string &command) { LOG->debug("date {}={}-{}, from {}, to {}, order by {}", date, RetrieveReadableDate(date).first, RetrieveReadableDate(date).second, from, to, order_by); // TODO + hash_t from_hash = SplitMix64Hash(from), to_hash = SplitMix64Hash(to); + std::vector valid_trains; + stop_register.QueryDirectTrains(date, from_hash, to_hash, valid_trains); + std::vector> valid_trains_full; + size_t len = valid_trains.size(); + for (size_t i = 0; i < len; i++) { + valid_trains_full[i].first = valid_trains[i]; + } response_stream << "[" << command_id << "] QueryTicket"; return response_stream.str(); }