Change station cargo history storage format
Use uint16 to avoid truncation issues Don't reserve memory for unused cargoes Store history as ring buffer Update history graph immediately on storage date Show total waiting cargo
This commit is contained in:
@@ -1660,6 +1660,7 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
Scrollbar *vscroll; ///< Cargo list scrollbar.
|
Scrollbar *vscroll; ///< Cargo list scrollbar.
|
||||||
uint legend_width {}; ///< Width of legend 'blob'.
|
uint legend_width {}; ///< Width of legend 'blob'.
|
||||||
CargoTypes legend_excluded_cargo;
|
CargoTypes legend_excluded_cargo;
|
||||||
|
CargoTypes present_cargoes;
|
||||||
|
|
||||||
StationCargoGraphWindow(WindowDesc *desc, WindowNumber window) :
|
StationCargoGraphWindow(WindowDesc *desc, WindowNumber window) :
|
||||||
BaseGraphWindow(desc, WID_SCG_GRAPH, STR_JUST_COMMA)
|
BaseGraphWindow(desc, WID_SCG_GRAPH, STR_JUST_COMMA)
|
||||||
@@ -1674,10 +1675,9 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
|
|
||||||
this->CreateNestedTree();
|
this->CreateNestedTree();
|
||||||
this->vscroll = this->GetScrollbar(WID_SCG_MATRIX_SCROLLBAR);
|
this->vscroll = this->GetScrollbar(WID_SCG_MATRIX_SCROLLBAR);
|
||||||
this->vscroll->SetCount(_sorted_standard_cargo_specs_size);
|
|
||||||
|
|
||||||
/* Initialise the data set */
|
/* Initialise the data set */
|
||||||
this->OnHundredthTick();
|
this->FillGraphData();
|
||||||
|
|
||||||
this->FinishInitNested(window);
|
this->FinishInitNested(window);
|
||||||
}
|
}
|
||||||
@@ -1687,17 +1687,6 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
/* Width of the legend blob. */
|
/* Width of the legend blob. */
|
||||||
this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5;
|
this->legend_width = (FONT_HEIGHT_SMALL - ScaleFontTrad(1)) * 8 / 5;
|
||||||
this->legend_excluded_cargo = 0;
|
this->legend_excluded_cargo = 0;
|
||||||
|
|
||||||
const Station* station = Station::GetIfValid(this->station_id);
|
|
||||||
|
|
||||||
if (station == nullptr) return;
|
|
||||||
|
|
||||||
const CargoSpec *cs;
|
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
|
||||||
if (station->goods[cs->Index()].cargo.AvailableCount() == 0) {
|
|
||||||
SetBit(legend_excluded_cargo, cs->Index());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStringParameters(int widget) const override
|
void SetStringParameters(int widget) const override
|
||||||
@@ -1714,6 +1703,7 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
uint8 i = 0;
|
uint8 i = 0;
|
||||||
const CargoSpec *cs;
|
const CargoSpec *cs;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||||
|
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||||
if (HasBit(legend_excluded_cargo, cs->Index())) SetBit(this->excluded_data, i);
|
if (HasBit(legend_excluded_cargo, cs->Index())) SetBit(this->excluded_data, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1761,6 +1751,7 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
|
|
||||||
const CargoSpec *cs;
|
const CargoSpec *cs;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||||
|
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||||
if (pos-- > 0) continue;
|
if (pos-- > 0) continue;
|
||||||
if (--max < 0) break;
|
if (--max < 0) break;
|
||||||
|
|
||||||
@@ -1786,17 +1777,18 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_SCG_ENABLE_CARGOES:
|
case WID_SCG_ENABLE_CARGOES:
|
||||||
/* Remove all cargoes from the excluded lists. */
|
/* Remove all cargoes from the excluded lists. */
|
||||||
legend_excluded_cargo = 0;
|
this->legend_excluded_cargo = 0;
|
||||||
this->excluded_data = 0;
|
this->excluded_data = 0;
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_SCG_DISABLE_CARGOES: {
|
case WID_SCG_DISABLE_CARGOES: {
|
||||||
/* Add all cargoes to the excluded lists. */
|
/* Add all cargoes to the excluded lists. */
|
||||||
|
this->legend_excluded_cargo = ~static_cast<CargoTypes>(0);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
const CargoSpec *cs;
|
const CargoSpec *cs;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||||
SetBit(legend_excluded_cargo, cs->Index());
|
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||||
SetBit(this->excluded_data, i);
|
SetBit(this->excluded_data, i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1810,6 +1802,7 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
|
|
||||||
const CargoSpec *cs;
|
const CargoSpec *cs;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||||
|
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||||
if (row-- > 0) continue;
|
if (row-- > 0) continue;
|
||||||
|
|
||||||
ToggleBit(legend_excluded_cargo, cs->Index());
|
ToggleBit(legend_excluded_cargo, cs->Index());
|
||||||
@@ -1840,25 +1833,32 @@ struct StationCargoGraphWindow final : BaseGraphWindow {
|
|||||||
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
||||||
{
|
{
|
||||||
if (!gui_scope) return;
|
if (!gui_scope) return;
|
||||||
this->OnHundredthTick();
|
this->FillGraphData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnHundredthTick() override
|
void FillGraphData()
|
||||||
{
|
{
|
||||||
this->UpdateExcludedData();
|
|
||||||
|
|
||||||
const Station* station = Station::GetIfValid(this->station_id);
|
const Station* station = Station::GetIfValid(this->station_id);
|
||||||
|
|
||||||
if (station == nullptr) return;
|
if (station == nullptr) return;
|
||||||
|
|
||||||
|
this->present_cargoes = station->station_cargo_history_cargoes;
|
||||||
|
this->vscroll->SetCount(CountBits(this->present_cargoes));
|
||||||
|
|
||||||
|
this->UpdateExcludedData();
|
||||||
|
|
||||||
uint8 i = 0;
|
uint8 i = 0;
|
||||||
const CargoSpec *cs;
|
const CargoSpec *cs;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
||||||
|
if (!HasBit(this->present_cargoes, cs->Index())) continue;
|
||||||
this->colours[i] = cs->legend_colour;
|
this->colours[i] = cs->legend_colour;
|
||||||
|
|
||||||
for (uint j = 0; j < MAX_STATION_CARGO_HISTORY_DAYS; j++) {
|
const auto &history = station->station_cargo_history[CountBits(this->present_cargoes & (cs->CargoTypesBit() - 1))];
|
||||||
|
|
||||||
this->cost[i][j] = station->station_cargo_history[cs->Index() * MAX_STATION_CARGO_HISTORY_DAYS + j] * STATION_CARGO_HISTORY_FACTOR;
|
uint offset = station->station_cargo_history_offset;
|
||||||
|
for (uint j = 0; j < MAX_STATION_CARGO_HISTORY_DAYS; j++) {
|
||||||
|
this->cost[i][j] = history[offset];
|
||||||
|
offset++;
|
||||||
|
if (offset == MAX_STATION_CARGO_HISTORY_DAYS) offset = 0;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@@ -459,7 +459,6 @@ static const SaveLoad _station_desc[] = {
|
|||||||
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES),
|
SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, SLV_127, SLV_EXTEND_CARGOTYPES),
|
||||||
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
SLE_CONDVAR(Station, always_accepted, SLE_UINT64, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||||
SLE_CONDNULL_X(32 * 24, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_22)),
|
SLE_CONDNULL_X(32 * 24, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP, SL_JOKER_1_22)),
|
||||||
SLE_CONDARR(Station, station_cargo_history, SLE_UINT8, NUM_CARGO * MAX_STATION_CARGO_HISTORY_DAYS, SL_JOKER_1_22, SL_MAX_VERSION),
|
|
||||||
|
|
||||||
SLE_END()
|
SLE_END()
|
||||||
};
|
};
|
||||||
|
@@ -78,7 +78,8 @@ Station::Station(TileIndex tile) :
|
|||||||
indtype(IT_INVALID),
|
indtype(IT_INVALID),
|
||||||
time_since_load(255),
|
time_since_load(255),
|
||||||
time_since_unload(255),
|
time_since_unload(255),
|
||||||
station_cargo_history{}
|
station_cargo_history_cargoes(0),
|
||||||
|
station_cargo_history_offset(0)
|
||||||
{
|
{
|
||||||
/* this->random_bits is set in Station::AddFacility() */
|
/* this->random_bits is set in Station::AddFacility() */
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "core/endian_type.hpp"
|
#include "core/endian_type.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -808,7 +809,9 @@ public:
|
|||||||
IndustryList industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
|
IndustryList industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
|
||||||
Industry *industry; ///< NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
|
Industry *industry; ///< NOSAVE: Associated industry for neutral stations. (Rebuilt on load from Industry->st)
|
||||||
|
|
||||||
uint8 station_cargo_history[NUM_CARGO * MAX_STATION_CARGO_HISTORY_DAYS]; ///< Station history of waiting cargo.
|
CargoTypes station_cargo_history_cargoes; ///< Bitmask of cargoes in station_cargo_history
|
||||||
|
uint8 station_cargo_history_offset; ///< Start offset in station_cargo_history cargo ring buffer
|
||||||
|
std::vector<std::array<uint16, MAX_STATION_CARGO_HISTORY_DAYS>> station_cargo_history; ///< Station history of waiting cargo.
|
||||||
|
|
||||||
Station(TileIndex tile = INVALID_TILE);
|
Station(TileIndex tile = INVALID_TILE);
|
||||||
~Station();
|
~Station();
|
||||||
|
@@ -409,16 +409,26 @@ void Station::GetTileArea(TileArea *ta, StationType type) const
|
|||||||
*/
|
*/
|
||||||
void Station::UpdateCargoHistory()
|
void Station::UpdateCargoHistory()
|
||||||
{
|
{
|
||||||
const CargoSpec* cs;
|
uint storage_offset = 0;
|
||||||
FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) {
|
bool update_window = false;
|
||||||
auto amount = this->goods[cs->Index()].cargo.AvailableCount();
|
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||||
|
uint amount = this->goods[cs->Index()].cargo.TotalCount();
|
||||||
std::rotate(std::begin(this->station_cargo_history) + cs->Index() * MAX_STATION_CARGO_HISTORY_DAYS,
|
if (!HasBit(this->station_cargo_history_cargoes, cs->Index())) {
|
||||||
std::begin(this->station_cargo_history) + cs->Index() * MAX_STATION_CARGO_HISTORY_DAYS + 1,
|
if (amount == 0) {
|
||||||
std::begin(this->station_cargo_history) + (cs->Index() + 1) * MAX_STATION_CARGO_HISTORY_DAYS);
|
/* No cargo present, and no history stored for this cargo, no work to do */
|
||||||
|
continue;
|
||||||
this->station_cargo_history[(cs->Index() + 1) * MAX_STATION_CARGO_HISTORY_DAYS - 1] = std::clamp(amount / STATION_CARGO_HISTORY_FACTOR, (uint)0, (uint)UINT8_MAX);
|
} else {
|
||||||
|
if (this->station_cargo_history_cargoes == 0) update_window = true;
|
||||||
|
SetBit(this->station_cargo_history_cargoes, cs->Index());
|
||||||
|
this->station_cargo_history.emplace(this->station_cargo_history.begin() + storage_offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
this->station_cargo_history[storage_offset][this->station_cargo_history_offset] = static_cast<uint16>(std::clamp<uint>(amount, (uint)0, (uint)UINT16_MAX));
|
||||||
|
storage_offset++;
|
||||||
|
}
|
||||||
|
this->station_cargo_history_offset++;
|
||||||
|
if (this->station_cargo_history_offset == MAX_STATION_CARGO_HISTORY_DAYS) this->station_cargo_history_offset = 0;
|
||||||
|
if (update_window) InvalidateWindowData(WC_STATION_VIEW, this->index, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4265,6 +4275,7 @@ void StationDailyLoop()
|
|||||||
for (Station *st : Station::Iterate()) {
|
for (Station *st : Station::Iterate()) {
|
||||||
st->UpdateCargoHistory();
|
st->UpdateCargoHistory();
|
||||||
}
|
}
|
||||||
|
InvalidateWindowClassesData(WC_STATION_CARGO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1366,6 +1366,12 @@ struct StationViewWindow : public Window {
|
|||||||
SetViewportCatchmentStation(Station::Get(this->window_number), false);
|
SetViewportCatchmentStation(Station::Get(this->window_number), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnInit() override
|
||||||
|
{
|
||||||
|
const Station *st = Station::Get(this->window_number);
|
||||||
|
SetWidgetDisabledState(WID_SV_HISTORY, st->station_cargo_history_cargoes == 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a certain cargo entry characterized by source/next/dest station, cargo ID and amount of cargo at the
|
* Show a certain cargo entry characterized by source/next/dest station, cargo ID and amount of cargo at the
|
||||||
* right place in the cargo view. I.e. update as many rows as are expanded following that characterization.
|
* right place in the cargo view. I.e. update as many rows as are expanded following that characterization.
|
||||||
|
@@ -28,7 +28,6 @@ static const StationID NEW_STATION = 0xFFFE;
|
|||||||
static const StationID INVALID_STATION = 0xFFFF;
|
static const StationID INVALID_STATION = 0xFFFF;
|
||||||
|
|
||||||
static const uint MAX_STATION_CARGO_HISTORY_DAYS = 24;
|
static const uint MAX_STATION_CARGO_HISTORY_DAYS = 24;
|
||||||
static const uint STATION_CARGO_HISTORY_FACTOR = 25;
|
|
||||||
|
|
||||||
typedef SmallStack<StationID, StationID, INVALID_STATION, 8, 0xFFFD> StationIDStack;
|
typedef SmallStack<StationID, StationID, INVALID_STATION, 8, 0xFFFD> StationIDStack;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user