fixed fatal bugs in query_ticket
This commit is contained in:
@ -12,6 +12,7 @@ struct stop_register_t {
|
||||
hash_t train_ID_hash;
|
||||
uint16_t type : 1;
|
||||
uint16_t startTime : 12;
|
||||
uint8_t stop_id;
|
||||
};
|
||||
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;
|
||||
@ -37,6 +38,9 @@ class StopRegister : public DataDriverBase {
|
||||
int actual_start_date;
|
||||
int leave_time_stamp;
|
||||
int arrive_time_stamp;
|
||||
int from_stop_id;
|
||||
int to_stop_id;
|
||||
int saleDate_beg;
|
||||
};
|
||||
// for satety, all the copy/move operations are deleted, please manage it using pointer
|
||||
StopRegister &operator=(const StopRegister &) = delete;
|
||||
@ -73,7 +77,7 @@ class StopRegister : public DataDriverBase {
|
||||
}
|
||||
inline void AddStopInfo(hash_t station_hash, hash_t train_hash, uint16_t true_saleDate_beg,
|
||||
uint16_t true_saleDate_end, uint16_t startTime, uint16_t arrive_time_offset,
|
||||
uint16_t leave_time_offset) {
|
||||
uint16_t leave_time_offset, uint8_t stop_id) {
|
||||
MinimalTrainRecord record_arrive, record_leave;
|
||||
const static int June_1st_2024 = 152;
|
||||
record_arrive.saleDate_beg = true_saleDate_beg - June_1st_2024;
|
||||
@ -83,10 +87,10 @@ class StopRegister : public DataDriverBase {
|
||||
record_leave.saleDate_end = true_saleDate_end - June_1st_2024;
|
||||
record_leave.vis_time_offset = leave_time_offset;
|
||||
if (arrive_time_offset != uint16_t(-1))
|
||||
bpt_indexer->Put({station_hash, train_hash, 0, startTime},
|
||||
bpt_indexer->Put({station_hash, train_hash, 0, startTime, stop_id},
|
||||
*reinterpret_cast<default_numeric_index_t *>(&record_arrive));
|
||||
if (leave_time_offset != uint16_t(-1))
|
||||
bpt_indexer->Put({station_hash, train_hash, 1, startTime},
|
||||
bpt_indexer->Put({station_hash, train_hash, 1, startTime, stop_id},
|
||||
*reinterpret_cast<default_numeric_index_t *>(&record_leave));
|
||||
}
|
||||
inline void QueryDirectTrains(uint32_t date, hash_t from_station_ID, hash_t to_station_ID,
|
||||
@ -102,17 +106,24 @@ class StopRegister : public DataDriverBase {
|
||||
++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) continue;
|
||||
if (date - delta_days < true_saleDate_beg || date - delta_days > true_saleDate_end) {
|
||||
++it_from;
|
||||
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;
|
||||
entry.leave_time_stamp = entry.actual_start_date * 1440 + actual_time;
|
||||
entry.from_stop_id = key_from.stop_id;
|
||||
entry.saleDate_beg = true_saleDate_beg;
|
||||
while (it_to != bpt_indexer->end_const()) {
|
||||
const auto &key_to = it_to.GetKey();
|
||||
const auto &value_to = it_to.GetValue();
|
||||
@ -121,10 +132,14 @@ class StopRegister : public DataDriverBase {
|
||||
++it_to;
|
||||
continue;
|
||||
}
|
||||
// LOG->debug("it_to now checks 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.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 +
|
||||
entry.arrive_time_stamp = entry.actual_start_date * 1440 + startTime +
|
||||
(*reinterpret_cast<const MinimalTrainRecord *>(&value_to)).vis_time_offset;
|
||||
entry.to_stop_id = key_to.stop_id;
|
||||
res.push_back(entry);
|
||||
++it_to;
|
||||
break;
|
||||
}
|
||||
|
@ -234,6 +234,7 @@ std::string TicketSystemEngine::ReleaseTrain(const std::string &command) {
|
||||
}
|
||||
}
|
||||
hash_t train_id_hash = SplitMix64Hash(trainID);
|
||||
LOG->debug("hash({})={}", trainID, train_id_hash);
|
||||
CoreTrainData core_train_data;
|
||||
try {
|
||||
core_train_data_storage.Get(train_id_hash, core_train_data);
|
||||
@ -262,7 +263,7 @@ std::string TicketSystemEngine::ReleaseTrain(const std::string &command) {
|
||||
}
|
||||
stop_register.AddStopInfo(core_train_data.stations_hash[i], train_id_hash, core_train_data.saleDate_beg,
|
||||
core_train_data.saleDate_end, core_train_data.startTime, arrive_time_offset,
|
||||
leave_time_offset);
|
||||
leave_time_offset, i);
|
||||
}
|
||||
response_stream << '[' << command_id << "] 0";
|
||||
return response_stream.str();
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
@ -51,12 +52,74 @@ std::string TicketSystemEngine::QueryTicket(const std::string &command) {
|
||||
hash_t from_hash = SplitMix64Hash(from), to_hash = SplitMix64Hash(to);
|
||||
std::vector<StopRegister::DirectTrainInfo> valid_trains;
|
||||
stop_register.QueryDirectTrains(date, from_hash, to_hash, valid_trains);
|
||||
std::vector<std::pair<StopRegister::DirectTrainInfo, AdditionalTrainInfo>> valid_trains_full;
|
||||
size_t len = valid_trains.size();
|
||||
std::vector<std::pair<StopRegister::DirectTrainInfo, AdditionalTrainInfo>> valid_trains_full(len);
|
||||
LOG->debug("retrieving full data");
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
valid_trains_full[i].first = valid_trains[i];
|
||||
TicketPriceData ticket_price_data;
|
||||
SeatsData seats_data;
|
||||
int from_station_id = valid_trains[i].from_stop_id;
|
||||
int to_station_id = valid_trains[i].to_stop_id;
|
||||
ticket_price_data_storage.Get(valid_trains[i].train_ID_hash, ticket_price_data);
|
||||
LOG->debug("analyzing train {} from {} to {}", ticket_price_data.trainID, from_station_id, to_station_id);
|
||||
seats_data_storage.Get(
|
||||
{valid_trains[i].train_ID_hash, valid_trains[i].actual_start_date - valid_trains[i].saleDate_beg}, seats_data);
|
||||
strcpy(valid_trains_full[i].second.trainID, ticket_price_data.trainID);
|
||||
int total_price = 0;
|
||||
for (int j = from_station_id; j < to_station_id; j++) {
|
||||
total_price += ticket_price_data.price[j];
|
||||
}
|
||||
valid_trains_full[i].second.price = total_price;
|
||||
int seats = seats_data.seat[from_station_id];
|
||||
for (int j = from_station_id + 1; j < to_station_id; j++) {
|
||||
seats = std::min(seats, (int)seats_data.seat[j]);
|
||||
}
|
||||
valid_trains_full[i].second.seats = seats;
|
||||
}
|
||||
LOG->debug("successfully retrieved full data");
|
||||
std::vector<int> valid_trains_full_index(len);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
valid_trains_full_index[i] = i;
|
||||
}
|
||||
if (order_by == "time") {
|
||||
auto cmp = [&valid_trains_full](int a, int b) {
|
||||
int time_cost_a = valid_trains_full[a].first.arrive_time_stamp - valid_trains_full[a].first.leave_time_stamp;
|
||||
int time_cost_b = valid_trains_full[b].first.arrive_time_stamp - valid_trains_full[b].first.leave_time_stamp;
|
||||
if (time_cost_a != time_cost_b) return time_cost_a < time_cost_b;
|
||||
return strcmp(valid_trains_full[a].second.trainID, valid_trains_full[b].second.trainID) < 0;
|
||||
};
|
||||
std::sort(valid_trains_full_index.begin(), valid_trains_full_index.end(), cmp);
|
||||
} else {
|
||||
// order by price
|
||||
auto cmp = [&valid_trains_full](int a, int b) {
|
||||
if (valid_trains_full[a].second.price != valid_trains_full[b].second.price)
|
||||
return valid_trains_full[a].second.price < valid_trains_full[b].second.price;
|
||||
return strcmp(valid_trains_full[a].second.trainID, valid_trains_full[b].second.trainID) < 0;
|
||||
};
|
||||
std::sort(valid_trains_full_index.begin(), valid_trains_full_index.end(), cmp);
|
||||
}
|
||||
response_stream << "[" << command_id << "] " << len;
|
||||
for (int i = 0; i < len; i++) {
|
||||
response_stream << '\n';
|
||||
response_stream << valid_trains_full[valid_trains_full_index[i]].second.trainID << ' ' << from << ' ';
|
||||
int leave_time_stamp = valid_trains_full[valid_trains_full_index[i]].first.leave_time_stamp;
|
||||
int leave_time_month, leave_time_day, leave_time_hour, leave_time_minute;
|
||||
RetrieveReadableTimeStamp(leave_time_stamp, leave_time_month, leave_time_day, leave_time_hour, leave_time_minute);
|
||||
response_stream << std::setw(2) << std::setfill('0') << leave_time_month << '-' << std::setw(2) << std::setfill('0')
|
||||
<< leave_time_day << ' ' << std::setw(2) << std::setfill('0') << leave_time_hour << ':'
|
||||
<< std::setw(2) << std::setfill('0') << leave_time_minute;
|
||||
response_stream << " -> " << to << ' ';
|
||||
int arrive_time_stamp = valid_trains_full[valid_trains_full_index[i]].first.arrive_time_stamp;
|
||||
int arrive_time_month, arrive_time_day, arrive_time_hour, arrive_time_minute;
|
||||
RetrieveReadableTimeStamp(arrive_time_stamp, arrive_time_month, arrive_time_day, arrive_time_hour,
|
||||
arrive_time_minute);
|
||||
response_stream << std::setw(2) << std::setfill('0') << arrive_time_month << '-' << std::setw(2)
|
||||
<< std::setfill('0') << arrive_time_day << ' ' << std::setw(2) << std::setfill('0')
|
||||
<< arrive_time_hour << ':' << std::setw(2) << std::setfill('0') << arrive_time_minute;
|
||||
response_stream << ' ' << valid_trains_full[valid_trains_full_index[i]].second.price << ' '
|
||||
<< valid_trains_full[valid_trains_full_index[i]].second.seats;
|
||||
}
|
||||
response_stream << "[" << command_id << "] QueryTicket";
|
||||
return response_stream.str();
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ add_test(NAME basic_3 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_3 --ski
|
||||
add_test(NAME basic_4 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_4 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||
add_test(NAME basic_5 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_5 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||
add_test(NAME basic_6 COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_6 --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||
add_test(NAME basic_extra COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_extra --skip-check --ignore-first-dependency --enable-tested-program-logging)
|
||||
add_test(NAME basic_extra COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py basic_extra --skip-check --ignore-first-dependency)
|
||||
add_test(NAME pressure_1_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_1_easy --skip-check --ignore-first-dependency)
|
||||
add_test(NAME pressure_2_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_2_easy --skip-check --ignore-first-dependency)
|
||||
add_test(NAME pressure_3_easy COMMAND ${PROJECT_SOURCE_DIR}/test/ojtest.py pressure_3_easy --skip-check --ignore-first-dependency)
|
||||
|
Reference in New Issue
Block a user