half way of query_transfer
This commit is contained in:
@ -51,6 +51,12 @@ class TicketSystemEngine {
|
|||||||
TransactionManager transaction_manager;
|
TransactionManager transaction_manager;
|
||||||
|
|
||||||
void PrepareExit();
|
void PrepareExit();
|
||||||
|
void CheckTransfer(hash_t train1_ID_hash, hash_t train2_ID_hash, const std::string &from_station,
|
||||||
|
const std::string &to_station, int date, bool &has_solution, std::string &res_train1_id,
|
||||||
|
std::string &res_train2_id, int &res_train1_leaving_time_stamp,
|
||||||
|
int &res_train1_arriving_time_stamp, int &res_train2_leaving_time_stamp,
|
||||||
|
int &res_train2_arriving_time_stamp, int &res_train1_price, int &res_train1_seat,
|
||||||
|
int &res_train2_price, int &res_train2_seat, std::string &res_transfer_station_name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const bool *its_time_to_exit_ptr = &its_time_to_exit;
|
const bool *its_time_to_exit_ptr = &its_time_to_exit;
|
||||||
|
@ -202,6 +202,52 @@ class StopRegister : public DataDriverBase {
|
|||||||
entry.to_stop_id = key_to.stop_id;
|
entry.to_stop_id = key_to.stop_id;
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
inline void FetchTrainLeavingFrom(uint32_t date, hash_t from_station_ID, std::vector<hash_t> &res) {
|
||||||
|
const static int June_1st_2024 = 152;
|
||||||
|
res.clear();
|
||||||
|
auto it_from = bpt_indexer->lower_bound_const({from_station_ID, 0});
|
||||||
|
while (it_from != bpt_indexer->end_const()) {
|
||||||
|
const auto &key_from = it_from.GetKey();
|
||||||
|
const auto &value_from = it_from.GetValue();
|
||||||
|
LOG->debug("it_from now tries to check station_id_hash {} train_id_hash {} stop_id {}", key_from.station_ID_hash,
|
||||||
|
key_from.train_ID_hash, key_from.stop_id);
|
||||||
|
if (key_from.station_ID_hash != from_station_ID) break;
|
||||||
|
if (key_from.type != 1) {
|
||||||
|
++it_from;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOG->debug("it_from now checks station_id_hash {} train_id_hash {} stop_id {}", key_from.station_ID_hash,
|
||||||
|
key_from.train_ID_hash, key_from.stop_id);
|
||||||
|
int true_saleDate_beg = (*reinterpret_cast<const MinimalTrainRecord *>(&value_from)).saleDate_beg + June_1st_2024;
|
||||||
|
int true_saleDate_end = (*reinterpret_cast<const MinimalTrainRecord *>(&value_from)).saleDate_end + June_1st_2024;
|
||||||
|
int leave_time_offset = (*reinterpret_cast<const MinimalTrainRecord *>(&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) {
|
||||||
|
++it_from;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res.push_back(key_from.train_ID_hash);
|
||||||
|
++it_from;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void FetchTrainArriavingAt(uint32_t date, hash_t to_station_ID, std::vector<hash_t> &res) {
|
||||||
|
res.clear();
|
||||||
|
auto it_to = bpt_indexer->lower_bound_const({to_station_ID, 0});
|
||||||
|
while (it_to != bpt_indexer->end_const()) {
|
||||||
|
const auto &key_to = it_to.GetKey();
|
||||||
|
LOG->debug("it_to now tries to check station_id_hash {} train_id_hash {} stop_id {}", key_to.station_ID_hash,
|
||||||
|
key_to.train_ID_hash, key_to.stop_id);
|
||||||
|
if (key_to.station_ID_hash != to_station_ID) break;
|
||||||
|
if (key_to.type != 0) {
|
||||||
|
++it_to;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res.push_back(key_to.train_ID_hash);
|
||||||
|
++it_to;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -120,9 +122,15 @@ inline void RetrieveReadableTimeStamp(int full_time_stamp, int &month, int &day,
|
|||||||
minute = minute_id % 60;
|
minute = minute_id % 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline int GetFullTimeStamp(int month, int day, int hour, int minute) {
|
inline int GetFullTimeStamp(int month, int day, int hour, int minute) {
|
||||||
int day_id = GetCompactDate(month, day);
|
int day_id = GetCompactDate(month, day);
|
||||||
return day_id * 1440 + hour * 60 + minute;
|
return day_id * 1440 + hour * 60 + minute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void PrintFullTimeStamp(int full_time_stamp, std::ostream &os) {
|
||||||
|
int month, day, hour, minute;
|
||||||
|
RetrieveReadableTimeStamp(full_time_stamp, month, day, hour, minute);
|
||||||
|
os << std::setw(2) << std::setfill('0') << month << '-' << std::setw(2) << std::setfill('0') << day << ' '
|
||||||
|
<< std::setw(2) << std::setfill('0') << hour << ':' << std::setw(2) << std::setfill('0') << minute;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
@ -162,11 +162,165 @@ std::string TicketSystemEngine::QueryTransfer(const std::string &command) {
|
|||||||
}
|
}
|
||||||
LOG->debug("date {}={}-{}, from {}, to {}, order by {}", date, RetrieveReadableDate(date).first,
|
LOG->debug("date {}={}-{}, from {}, to {}, order by {}", date, RetrieveReadableDate(date).first,
|
||||||
RetrieveReadableDate(date).second, from, to, order_by);
|
RetrieveReadableDate(date).second, from, to, order_by);
|
||||||
// TODO
|
bool has_solution = false;
|
||||||
response_stream << "[" << command_id << "] 0";
|
std::vector<hash_t> trains_leaving_from_from;
|
||||||
|
std::vector<hash_t> trains_arriving_at_dest;
|
||||||
|
hash_t from_station_hash = SplitMix64Hash(from), to_station_hash = SplitMix64Hash(to);
|
||||||
|
stop_register.FetchTrainLeavingFrom(date, from_station_hash, trains_leaving_from_from);
|
||||||
|
stop_register.FetchTrainArriavingAt(date, to_station_hash, trains_arriving_at_dest);
|
||||||
|
LOG->debug("now we need to check {} * {} possible solutions", trains_leaving_from_from.size(),
|
||||||
|
trains_arriving_at_dest.size());
|
||||||
|
std::string train1_id, train2_id;
|
||||||
|
std::string transfer_station_id;
|
||||||
|
int train1_leaving_time_stamp, train1_arriving_time_stamp;
|
||||||
|
int train2_leaving_time_stamp, train2_arriving_time_stamp;
|
||||||
|
int train1_price, train1_seats;
|
||||||
|
int train2_price, train2_seats;
|
||||||
|
const size_t len_1 = trains_leaving_from_from.size(), len_2 = trains_arriving_at_dest.size();
|
||||||
|
for (size_t i = 0; i < len_1; i++) {
|
||||||
|
for (size_t j = 0; j < len_2; j++) {
|
||||||
|
CheckTransfer(trains_leaving_from_from[i], trains_arriving_at_dest[j], from, to, date, has_solution, train1_id,
|
||||||
|
train2_id, train1_leaving_time_stamp, train1_arriving_time_stamp, train2_leaving_time_stamp,
|
||||||
|
train2_arriving_time_stamp, train1_price, train1_seats, train2_price, train2_seats,
|
||||||
|
transfer_station_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_solution) {
|
||||||
|
response_stream << "[" << command_id << "] 0";
|
||||||
|
return response_stream.str();
|
||||||
|
}
|
||||||
|
response_stream << '[' << command_id << "] ";
|
||||||
|
response_stream << train1_id << " " << from << " ";
|
||||||
|
PrintFullTimeStamp(train1_leaving_time_stamp, response_stream);
|
||||||
|
response_stream << " -> " << transfer_station_id << " ";
|
||||||
|
PrintFullTimeStamp(train1_arriving_time_stamp, response_stream);
|
||||||
|
response_stream << " " << train1_price << " " << train1_seats << '\n';
|
||||||
|
response_stream << train2_id << " " << transfer_station_id << " ";
|
||||||
|
PrintFullTimeStamp(train2_leaving_time_stamp, response_stream);
|
||||||
|
response_stream << " -> " << to << " ";
|
||||||
|
PrintFullTimeStamp(train2_arriving_time_stamp, response_stream);
|
||||||
|
response_stream << " " << train2_price << " " << train2_seats;
|
||||||
return response_stream.str();
|
return response_stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TicketSystemEngine::CheckTransfer(hash_t train1_ID_hash, hash_t train2_ID_hash, const std::string &from_station,
|
||||||
|
const std::string &to_station, int date, bool &has_solution,
|
||||||
|
std::string &res_train1_id, std::string &res_train2_id,
|
||||||
|
int &res_train1_leaving_time_stamp, int &res_train1_arriving_time_stamp,
|
||||||
|
int &res_train2_leaving_time_stamp, int &res_train2_arriving_time_stamp,
|
||||||
|
int &res_train1_price, int &res_train1_seat, int &res_train2_price,
|
||||||
|
int &res_train2_seat, std::string &res_transfer_station_name) {
|
||||||
|
std::map<hash_t, int> transfer_mp;
|
||||||
|
hash_t from_station_hash = SplitMix64Hash(from_station), to_station_hash = SplitMix64Hash(to_station);
|
||||||
|
CoreTrainData train1_core_data, train2_core_data;
|
||||||
|
core_train_data_storage.Get(train1_ID_hash, train1_core_data);
|
||||||
|
core_train_data_storage.Get(train2_ID_hash, train2_core_data);
|
||||||
|
TicketPriceData train1_price_data, train2_price_data;
|
||||||
|
ticket_price_data_storage.Get(train1_ID_hash, train1_price_data);
|
||||||
|
ticket_price_data_storage.Get(train2_ID_hash, train2_price_data);
|
||||||
|
int train1_price_sum[100] = {0}, train2_price_sum[100] = {0};
|
||||||
|
for (int i = 1; i < train1_core_data.stationNum; i++) {
|
||||||
|
train1_price_sum[i] = train1_price_sum[i - 1] + train1_price_data.price[i - 1];
|
||||||
|
}
|
||||||
|
for (int i = 1; i < train2_core_data.stationNum; i++) {
|
||||||
|
train2_price_sum[i] = train2_price_sum[i - 1] + train2_price_data.price[i - 1];
|
||||||
|
}
|
||||||
|
int train1_arrive_time_offeset[100] = {0}, train1_leave_time_offset[100] = {0};
|
||||||
|
int train2_arrive_time_offeset[100] = {0}, train2_leave_time_offset[100] = {0};
|
||||||
|
for (int i = 1; i < train1_core_data.stationNum; i++) {
|
||||||
|
train1_arrive_time_offeset[i] = train1_leave_time_offset[i - 1] + train1_core_data.travelTime[i - 1];
|
||||||
|
train1_leave_time_offset[i] = train1_arrive_time_offeset[i] + train1_core_data.stopoverTime[i];
|
||||||
|
}
|
||||||
|
for (int i = 1; i < train2_core_data.stationNum; i++) {
|
||||||
|
train2_arrive_time_offeset[i] = train2_leave_time_offset[i - 1] + train2_core_data.travelTime[i - 1];
|
||||||
|
train2_leave_time_offset[i] = train2_arrive_time_offeset[i] + train2_core_data.stopoverTime[i];
|
||||||
|
}
|
||||||
|
bool has_meet_begin_station = false;
|
||||||
|
int start_station_offset = 0;
|
||||||
|
for (int i = 0; i < train1_core_data.stationNum; i++) {
|
||||||
|
if (train1_core_data.stations_hash[i] == from_station_hash) {
|
||||||
|
has_meet_begin_station = true;
|
||||||
|
start_station_offset = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (has_meet_begin_station) {
|
||||||
|
transfer_mp[train1_core_data.stations_hash[i]] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool has_meet_end_station = false;
|
||||||
|
int dest_station_offset = 0;
|
||||||
|
for (int i = train2_core_data.stationNum - 1; i >= 0; i--) {
|
||||||
|
if (train2_core_data.stations_hash[i] == to_station_hash) {
|
||||||
|
has_meet_end_station = true;
|
||||||
|
dest_station_offset = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOG->debug("start_station_offset {} dest_station_offset {}", start_station_offset, dest_station_offset);
|
||||||
|
if (has_meet_end_station && transfer_mp.find(train2_core_data.stations_hash[i]) != transfer_mp.end()) {
|
||||||
|
int transfer_station_offset = transfer_mp[train2_core_data.stations_hash[i]];
|
||||||
|
int train1_actual_time = train1_core_data.startTime + train1_leave_time_offset[start_station_offset];
|
||||||
|
int train1_delta_days = train1_actual_time / 1440;
|
||||||
|
int train1_actual_start_date = date - train1_delta_days;
|
||||||
|
if (train1_actual_start_date < train1_core_data.saleDate_beg ||
|
||||||
|
train1_actual_start_date > train1_core_data.saleDate_end) {
|
||||||
|
throw std::runtime_error("there are mistakes in StopRegister::FetchTrainLeavingFrom");
|
||||||
|
}
|
||||||
|
int cur_train1_leaving_time_stamp = train1_actual_start_date * 1440 + train1_actual_time;
|
||||||
|
int cur_train1_arriving_time_stamp = train1_actual_start_date * 1440 + train1_core_data.startTime +
|
||||||
|
train1_arrive_time_offeset[transfer_station_offset];
|
||||||
|
int train2_earliest_leaving_time_stamp =
|
||||||
|
train2_core_data.saleDate_beg * 1440 + train2_core_data.startTime + train2_leave_time_offset[i];
|
||||||
|
int train2_latest_leaving_time_stamp =
|
||||||
|
train2_core_data.saleDate_end * 1440 + train2_core_data.startTime + train2_leave_time_offset[i];
|
||||||
|
if (cur_train1_arriving_time_stamp > train2_latest_leaving_time_stamp) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::stringstream test_buf;
|
||||||
|
PrintFullTimeStamp(train2_earliest_leaving_time_stamp, test_buf);
|
||||||
|
LOG->debug("train2_earliest_leaving_time_stamp: {}", test_buf.str());
|
||||||
|
int cur_train2_leaving_time_stamp = train2_earliest_leaving_time_stamp;
|
||||||
|
if (cur_train2_leaving_time_stamp < cur_train1_arriving_time_stamp) {
|
||||||
|
int delta_count = (cur_train1_arriving_time_stamp - cur_train2_leaving_time_stamp + 1440 - 1) / 1440;
|
||||||
|
cur_train2_leaving_time_stamp += delta_count * 1440;
|
||||||
|
}
|
||||||
|
int cur_train2_arriving_time_stamp =
|
||||||
|
cur_train2_leaving_time_stamp + train2_arrive_time_offeset[dest_station_offset] - train2_leave_time_offset[i];
|
||||||
|
if (!has_solution) {
|
||||||
|
// just copy the first solution
|
||||||
|
has_solution = true;
|
||||||
|
res_train1_id = train1_price_data.trainID;
|
||||||
|
res_train2_id = train2_price_data.trainID;
|
||||||
|
res_train1_leaving_time_stamp = cur_train1_leaving_time_stamp;
|
||||||
|
res_train1_arriving_time_stamp = cur_train1_arriving_time_stamp;
|
||||||
|
res_train2_leaving_time_stamp = cur_train2_leaving_time_stamp;
|
||||||
|
res_train2_arriving_time_stamp = cur_train2_arriving_time_stamp;
|
||||||
|
res_train1_price = train1_price_sum[transfer_station_offset] - train1_price_sum[start_station_offset];
|
||||||
|
res_train2_price = train2_price_sum[dest_station_offset] - train2_price_sum[i];
|
||||||
|
StationNameData station_name_data;
|
||||||
|
station_name_data_storage.Get(train1_ID_hash, station_name_data);
|
||||||
|
auto &str = station_name_data.name[transfer_station_offset];
|
||||||
|
res_transfer_station_name = "";
|
||||||
|
for (int i = 0; i < 40 && str[i] != '\0'; i++) res_transfer_station_name.push_back(str[i]);
|
||||||
|
SeatsData train1_seats_data, train2_seats_data;
|
||||||
|
seats_data_storage.Get({train1_ID_hash, train1_actual_start_date - train1_core_data.saleDate_beg},
|
||||||
|
train1_seats_data);
|
||||||
|
int train2_actual_start_date = cur_train2_leaving_time_stamp / 1440;
|
||||||
|
seats_data_storage.Get({train2_ID_hash, train2_actual_start_date - train2_core_data.saleDate_beg},
|
||||||
|
train2_seats_data);
|
||||||
|
res_train1_seat = train1_seats_data.seat[start_station_offset];
|
||||||
|
for (int j = start_station_offset + 1; j < transfer_station_offset; j++) {
|
||||||
|
res_train1_seat = std::min(res_train1_seat, (int)train1_seats_data.seat[j]);
|
||||||
|
}
|
||||||
|
res_train2_seat = train2_seats_data.seat[i];
|
||||||
|
for (int j = i + 1; j < dest_station_offset; j++) {
|
||||||
|
res_train2_seat = std::min(res_train2_seat, (int)train2_seats_data.seat[j]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string TicketSystemEngine::BuyTicket(const std::string &command) {
|
std::string TicketSystemEngine::BuyTicket(const std::string &command) {
|
||||||
command_id_t command_id;
|
command_id_t command_id;
|
||||||
sscanf(command.c_str(), "[%llu]", &command_id);
|
sscanf(command.c_str(), "[%llu]", &command_id);
|
||||||
|
Reference in New Issue
Block a user