mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
2 Commits
6fa7dd17e3
...
894e6bb087
Author | SHA1 | Date |
---|---|---|
|
894e6bb087 | |
|
c677c40d53 |
|
@ -410,7 +410,7 @@ void VehicleCargoList::AgeCargo()
|
||||||
return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
|
return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
|
||||||
} else if (cargo_next == current_station) {
|
} else if (cargo_next == current_station) {
|
||||||
return MTA_DELIVER;
|
return MTA_DELIVER;
|
||||||
} else if (next_station.Contains(cargo_next)) {
|
} else if (next_station.Contains(cargo_next.base())) {
|
||||||
return MTA_KEEP;
|
return MTA_KEEP;
|
||||||
} else {
|
} else {
|
||||||
return MTA_TRANSFER;
|
return MTA_TRANSFER;
|
||||||
|
@ -470,7 +470,7 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID
|
||||||
new_shares.ChangeShare(current_station, INT_MIN);
|
new_shares.ChangeShare(current_station, INT_MIN);
|
||||||
StationIDStack excluded = next_station;
|
StationIDStack excluded = next_station;
|
||||||
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
|
while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
|
||||||
new_shares.ChangeShare(excluded.Pop(), INT_MIN);
|
new_shares.ChangeShare(StationID{excluded.Pop()}, INT_MIN);
|
||||||
}
|
}
|
||||||
if (new_shares.GetShares()->empty()) {
|
if (new_shares.GetShares()->empty()) {
|
||||||
cargo_next = StationID::Invalid();
|
cargo_next = StationID::Invalid();
|
||||||
|
@ -743,7 +743,7 @@ uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool incl
|
||||||
{
|
{
|
||||||
uint max_move = action.MaxMove();
|
uint max_move = action.MaxMove();
|
||||||
while (!next.IsEmpty()) {
|
while (!next.IsEmpty()) {
|
||||||
this->ShiftCargo(action, next.Pop());
|
this->ShiftCargo(action, StationID{next.Pop()});
|
||||||
if (action.MaxMove() == 0) break;
|
if (action.MaxMove() == 0) break;
|
||||||
}
|
}
|
||||||
if (include_invalid && action.MaxMove() > 0) {
|
if (include_invalid && action.MaxMove() > 0) {
|
||||||
|
@ -853,7 +853,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac
|
||||||
*/
|
*/
|
||||||
uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
|
uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
|
||||||
{
|
{
|
||||||
return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false);
|
return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid.base(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -555,7 +555,7 @@ public:
|
||||||
inline bool HasCargoFor(StationIDStack next) const
|
inline bool HasCargoFor(StationIDStack next) const
|
||||||
{
|
{
|
||||||
while (!next.IsEmpty()) {
|
while (!next.IsEmpty()) {
|
||||||
if (this->packets.find(next.Pop()) != this->packets.end()) return true;
|
if (this->packets.find(StationID{next.Pop()}) != this->packets.end()) return true;
|
||||||
}
|
}
|
||||||
/* Packets for StationID::Invalid() can go anywhere. */
|
/* Packets for StationID::Invalid() can go anywhere. */
|
||||||
return this->packets.find(StationID::Invalid()) != this->packets.end();
|
return this->packets.find(StationID::Invalid()) != this->packets.end();
|
||||||
|
|
|
@ -113,14 +113,13 @@ struct SmallStackItem {
|
||||||
* index types of the same length.
|
* index types of the same length.
|
||||||
* @tparam Titem Value type to be used.
|
* @tparam Titem Value type to be used.
|
||||||
* @tparam Tindex Index type to use for the pool.
|
* @tparam Tindex Index type to use for the pool.
|
||||||
* @tparam Tinvalid_value Value to construct invalid item to keep at the bottom of each stack.
|
* @tparam Tinvalid Invalid item to keep at the bottom of each stack.
|
||||||
* @tparam Tgrowth_step Growth step for pool.
|
* @tparam Tgrowth_step Growth step for pool.
|
||||||
* @tparam Tmax_size Maximum size for pool.
|
* @tparam Tmax_size Maximum size for pool.
|
||||||
*/
|
*/
|
||||||
template <typename Titem, typename Tindex, auto Tinvalid_value, Tindex Tgrowth_step, Tindex Tmax_size>
|
template <typename Titem, typename Tindex, Titem Tinvalid, Tindex Tgrowth_step, Tindex Tmax_size>
|
||||||
class SmallStack : public SmallStackItem<Titem, Tindex> {
|
class SmallStack : public SmallStackItem<Titem, Tindex> {
|
||||||
public:
|
public:
|
||||||
static constexpr Titem Tinvalid{Tinvalid_value};
|
|
||||||
|
|
||||||
typedef SmallStackItem<Titem, Tindex> Item;
|
typedef SmallStackItem<Titem, Tindex> Item;
|
||||||
|
|
||||||
|
|
18
src/gfx.cpp
18
src/gfx.cpp
|
@ -580,11 +580,10 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
||||||
|
|
||||||
const uint shadow_offset = ScaleGUITrad(1);
|
const uint shadow_offset = ScaleGUITrad(1);
|
||||||
|
|
||||||
auto draw_line = [&](const ParagraphLayouter::Line &line, bool do_shadow, int left, int min_x, int max_x, bool truncation, TextColour initial_colour) {
|
auto draw_line = [&](const ParagraphLayouter::Line &line, bool do_shadow, int left, int min_x, int max_x, bool truncation, TextColour &last_colour) {
|
||||||
const DrawPixelInfo *dpi = _cur_dpi;
|
const DrawPixelInfo *dpi = _cur_dpi;
|
||||||
int dpi_left = dpi->left;
|
int dpi_left = dpi->left;
|
||||||
int dpi_right = dpi->left + dpi->width - 1;
|
int dpi_right = dpi->left + dpi->width - 1;
|
||||||
TextColour last_colour = initial_colour;
|
|
||||||
|
|
||||||
for (int run_index = 0; run_index < line.CountRuns(); run_index++) {
|
for (int run_index = 0; run_index < line.CountRuns(); run_index++) {
|
||||||
const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index);
|
const ParagraphLayouter::VisualRun &run = line.GetVisualRun(run_index);
|
||||||
|
@ -594,10 +593,13 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
||||||
|
|
||||||
FontCache *fc = f->fc;
|
FontCache *fc = f->fc;
|
||||||
TextColour colour = f->colour;
|
TextColour colour = f->colour;
|
||||||
if (colour == TC_INVALID || HasFlag(initial_colour, TC_FORCED)) colour = initial_colour;
|
if (colour == TC_INVALID || HasFlag(last_colour, TC_FORCED)) {
|
||||||
|
colour = last_colour;
|
||||||
|
} else {
|
||||||
|
/* Update the last colour for the truncation ellipsis. */
|
||||||
|
last_colour = colour;
|
||||||
|
}
|
||||||
bool colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK;
|
bool colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK;
|
||||||
/* Update the last colour for the truncation ellipsis. */
|
|
||||||
last_colour = colour;
|
|
||||||
if (do_shadow && (!fc->GetDrawGlyphShadow() || !colour_has_shadow)) continue;
|
if (do_shadow && (!fc->GetDrawGlyphShadow() || !colour_has_shadow)) continue;
|
||||||
SetColourRemap(do_shadow ? TC_BLACK : colour);
|
SetColourRemap(do_shadow ? TC_BLACK : colour);
|
||||||
|
|
||||||
|
@ -623,16 +625,16 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
|
||||||
GfxMainBlitter(sprite, begin_x + (do_shadow ? shadow_offset : 0), top + (do_shadow ? shadow_offset : 0), BlitterMode::ColourRemap);
|
GfxMainBlitter(sprite, begin_x + (do_shadow ? shadow_offset : 0), top + (do_shadow ? shadow_offset : 0), BlitterMode::ColourRemap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return last_colour;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Draw shadow, then foreground */
|
/* Draw shadow, then foreground */
|
||||||
for (bool do_shadow : {true, false}) {
|
for (bool do_shadow : {true, false}) {
|
||||||
TextColour colour = draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation, default_colour);
|
TextColour last_colour = default_colour;
|
||||||
|
draw_line(line, do_shadow, left - offset_x, min_x, max_x, truncation, last_colour);
|
||||||
|
|
||||||
if (truncation) {
|
if (truncation) {
|
||||||
int x = (_current_text_dir == TD_RTL) ? left : (right - truncation_width);
|
int x = (_current_text_dir == TD_RTL) ? left : (right - truncation_width);
|
||||||
draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX, false, colour);
|
draw_line(*truncation_layout->front(), do_shadow, x, INT32_MIN, INT32_MAX, false, last_colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1842,7 +1842,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
|
||||||
p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
|
p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateValidHistory(i->valid_history, HISTORY_YEAR, TimerGameEconomy::month);
|
UpdateValidHistory(i->valid_history, TimerGameEconomy::month);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
|
if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
|
||||||
|
@ -2519,13 +2519,13 @@ Industry::AcceptedHistory SumHistory(std::span<const Industry::AcceptedHistory>
|
||||||
static void UpdateIndustryStatistics(Industry *i)
|
static void UpdateIndustryStatistics(Industry *i)
|
||||||
{
|
{
|
||||||
auto month = TimerGameEconomy::month;
|
auto month = TimerGameEconomy::month;
|
||||||
UpdateValidHistory(i->valid_history, HISTORY_YEAR, month);
|
UpdateValidHistory(i->valid_history, month);
|
||||||
|
|
||||||
for (auto &p : i->produced) {
|
for (auto &p : i->produced) {
|
||||||
if (IsValidCargoType(p.cargo)) {
|
if (IsValidCargoType(p.cargo)) {
|
||||||
if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
|
if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
|
||||||
|
|
||||||
RotateHistory(p.history, i->valid_history, HISTORY_YEAR, month);
|
RotateHistory(p.history, i->valid_history, month);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2534,7 +2534,7 @@ static void UpdateIndustryStatistics(Industry *i)
|
||||||
if (a.history == nullptr) continue;
|
if (a.history == nullptr) continue;
|
||||||
|
|
||||||
(*a.history)[THIS_MONTH].waiting = GetAndResetAccumulatedAverage<uint16_t>(a.accumulated_waiting);
|
(*a.history)[THIS_MONTH].waiting = GetAndResetAccumulatedAverage<uint16_t>(a.accumulated_waiting);
|
||||||
RotateHistory(*a.history, i->valid_history, HISTORY_YEAR, month);
|
RotateHistory(*a.history, i->valid_history, month);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,13 +42,13 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Erase all flows originating at a specific station.
|
* Erase all flows originating at a specific node.
|
||||||
* @param from StationID to erase flows for.
|
* @param from Node to erase flows for.
|
||||||
*/
|
*/
|
||||||
void LinkGraphJob::EraseFlows(StationID from)
|
void LinkGraphJob::EraseFlows(NodeID from)
|
||||||
{
|
{
|
||||||
for (NodeID node_id = 0; node_id < this->Size(); ++node_id) {
|
for (NodeID node_id = 0; node_id < this->Size(); ++node_id) {
|
||||||
(*this)[node_id].flows.erase(from);
|
(*this)[node_id].flows.erase(StationID{from});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ LinkGraphJob::~LinkGraphJob()
|
||||||
/* The station can have been deleted. Remove all flows originating from it then. */
|
/* The station can have been deleted. Remove all flows originating from it then. */
|
||||||
Station *st = Station::GetIfValid(from.base.station);
|
Station *st = Station::GetIfValid(from.base.station);
|
||||||
if (st == nullptr) {
|
if (st == nullptr) {
|
||||||
this->EraseFlows(from.base.station);
|
this->EraseFlows(node_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ LinkGraphJob::~LinkGraphJob()
|
||||||
* sure that everything is still consistent or ignore it otherwise. */
|
* sure that everything is still consistent or ignore it otherwise. */
|
||||||
GoodsEntry &ge = st->goods[this->Cargo()];
|
GoodsEntry &ge = st->goods[this->Cargo()];
|
||||||
if (ge.link_graph != this->link_graph.index || ge.node != node_id) {
|
if (ge.link_graph != this->link_graph.index || ge.node != node_id) {
|
||||||
this->EraseFlows(from.base.station);
|
this->EraseFlows(node_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ LinkGraphJob::~LinkGraphJob()
|
||||||
/* Delete old flows for source stations which have been deleted
|
/* Delete old flows for source stations which have been deleted
|
||||||
* from the new flows. This avoids flow cycles between old and
|
* from the new flows. This avoids flow cycles between old and
|
||||||
* new flows. */
|
* new flows. */
|
||||||
while (!erased.IsEmpty()) geflows.erase(erased.Pop());
|
while (!erased.IsEmpty()) geflows.erase(StationID{erased.Pop()});
|
||||||
} else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) {
|
} else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) {
|
||||||
/* Edge is fully restricted. */
|
/* Edge is fully restricted. */
|
||||||
flows.RestrictFlows(to);
|
flows.RestrictFlows(to);
|
||||||
|
|
|
@ -167,7 +167,7 @@ protected:
|
||||||
std::atomic<bool> job_completed = false; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
|
std::atomic<bool> job_completed = false; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
|
||||||
std::atomic<bool> job_aborted = false; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale.
|
std::atomic<bool> job_aborted = false; ///< Has the job been aborted. This is accessed by multiple threads and reads may be stale.
|
||||||
|
|
||||||
void EraseFlows(StationID from);
|
void EraseFlows(NodeID from);
|
||||||
void JoinThread();
|
void JoinThread();
|
||||||
void SpawnThread();
|
void SpawnThread();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
/** @file history.cpp Implementation of functions for storing historical data. */
|
/** @file history.cpp Implementation of functions for storing historical data. */
|
||||||
|
|
||||||
|
#ifndef HISTORY_CPP
|
||||||
|
#define HISTORY_CPP
|
||||||
|
|
||||||
#include "../stdafx.h"
|
#include "../stdafx.h"
|
||||||
|
|
||||||
#include "../core/bitmath_func.hpp"
|
#include "../core/bitmath_func.hpp"
|
||||||
|
@ -15,35 +18,26 @@
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
/**
|
static void UpdateValidHistory(ValidHistoryMask &valid_history, const HistoryRange &hr, uint cur_month)
|
||||||
* Update mask of valid records for a historical data.
|
|
||||||
* @note Call only for the largest history range sub-division.
|
|
||||||
* @param[in,out] valid_history Valid history records.
|
|
||||||
* @param hr History range to update mask for.
|
|
||||||
* @param cur_month Current economy month.
|
|
||||||
*/
|
|
||||||
void UpdateValidHistory(ValidHistoryMask &valid_history, const HistoryRange &hr, uint cur_month)
|
|
||||||
{
|
{
|
||||||
/* Update for subdivisions first. */
|
|
||||||
if (hr.hr != nullptr) UpdateValidHistory(valid_history, *hr.hr, cur_month);
|
|
||||||
|
|
||||||
/* No need to update if our last entry is marked valid. */
|
|
||||||
if (HasBit(valid_history, hr.last - 1)) return;
|
|
||||||
/* Is it the right time for this history range? */
|
|
||||||
if (cur_month % hr.total_division != 0) return;
|
if (cur_month % hr.total_division != 0) return;
|
||||||
/* Is the previous history range valid yet? */
|
|
||||||
if (hr.division != 1 && !HasBit(valid_history, hr.first - hr.division)) return;
|
if (hr.division != 1 && !HasBit(valid_history, hr.first - hr.division)) return;
|
||||||
|
|
||||||
SB(valid_history, hr.first, hr.records, GB(valid_history, hr.first, hr.records) << 1ULL | 1ULL);
|
SB(valid_history, hr.first, hr.records, GB(valid_history, hr.first, hr.records) << 1ULL | 1ULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if history data is valid, without extracting data.
|
* Update mask of valid records.
|
||||||
* @param valid_history Mask of valid history records.
|
* @param[in,out] valid_history Valid history records.
|
||||||
* @param hr History range to test.
|
* @param age Current economy month.
|
||||||
* @param age Age of data to test.
|
|
||||||
* @return True iff the data for history range and age is valid.
|
|
||||||
*/
|
*/
|
||||||
|
void UpdateValidHistory(ValidHistoryMask &valid_history, uint cur_month)
|
||||||
|
{
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_MONTH, cur_month);
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_QUARTER, cur_month);
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_YEAR, cur_month);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint age)
|
bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint age)
|
||||||
{
|
{
|
||||||
if (hr.hr == nullptr) {
|
if (hr.hr == nullptr) {
|
||||||
|
@ -54,7 +48,7 @@ bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint
|
||||||
} else {
|
} else {
|
||||||
if (age * hr.division < static_cast<uint>(hr.hr->periods - hr.division)) {
|
if (age * hr.division < static_cast<uint>(hr.hr->periods - hr.division)) {
|
||||||
uint start = age * hr.division + ((TimerGameEconomy::month / hr.hr->division) % hr.division);
|
uint start = age * hr.division + ((TimerGameEconomy::month / hr.hr->division) % hr.division);
|
||||||
return IsValidHistory(valid_history, *hr.hr, start);
|
return IsValidHistory(valid_history, *hr.hr, start/* + hr.division - 1*/);
|
||||||
}
|
}
|
||||||
if (age < hr.periods) {
|
if (age < hr.periods) {
|
||||||
uint slot = hr.first + age - ((hr.hr->periods / hr.division) - 1);
|
uint slot = hr.first + age - ((hr.hr->periods / hr.division) - 1);
|
||||||
|
@ -63,3 +57,5 @@ bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* HISTORY_CPP */
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include "../timer/timer_game_economy.h"
|
#include "../timer/timer_game_economy.h"
|
||||||
#include "history_type.hpp"
|
#include "history_type.hpp"
|
||||||
|
|
||||||
void UpdateValidHistory(ValidHistoryMask &valid_history, const HistoryRange &hr, uint cur_month);
|
void UpdateValidHistory(ValidHistoryMask &valid_history, uint cur_month);
|
||||||
bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint age);
|
bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint age);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,25 +29,19 @@ template <typename T>
|
||||||
T SumHistory(typename std::span<const T> history);
|
T SumHistory(typename std::span<const T> history);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate historical data.
|
* Rotate history.
|
||||||
* @note Call only for the largest history range sub-division.
|
|
||||||
* @tparam T type of history data element.
|
* @tparam T type of history data element.
|
||||||
* @param history Historical data to rotate.
|
* @param history Historical data to rotate.
|
||||||
* @param valid_history Mask of valid history records.
|
|
||||||
* @param hr History range to rotate..
|
|
||||||
* @param cur_month Current economy month.
|
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint cur_month)
|
void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint cur_month)
|
||||||
{
|
{
|
||||||
if (hr.hr != nullptr) RotateHistory(history, valid_history, *hr.hr, cur_month);
|
|
||||||
if (cur_month % hr.total_division != 0) return;
|
if (cur_month % hr.total_division != 0) return;
|
||||||
|
|
||||||
std::move_backward(std::next(std::begin(history), hr.first), std::next(std::begin(history), hr.last - 1), std::next(std::begin(history), hr.last));
|
std::move_backward(std::next(std::begin(history), hr.first), std::next(std::begin(history), hr.last - 1), std::next(std::begin(history), hr.last));
|
||||||
|
|
||||||
if (hr.total_division == 1) {
|
if (hr.division == 1) {
|
||||||
history[hr.first] = history[hr.first - 1];
|
history[hr.first] = history[hr.first - 1];
|
||||||
history.front() = {};
|
|
||||||
} else if (HasBit(valid_history, hr.first - hr.division)) {
|
} else if (HasBit(valid_history, hr.first - hr.division)) {
|
||||||
auto first = std::next(std::begin(history), hr.first - hr.division);
|
auto first = std::next(std::begin(history), hr.first - hr.division);
|
||||||
auto last = std::next(first, hr.division);
|
auto last = std::next(first, hr.division);
|
||||||
|
@ -55,6 +49,15 @@ void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, uint cur_month)
|
||||||
|
{
|
||||||
|
RotateHistory(history, valid_history, HISTORY_MONTH, cur_month);
|
||||||
|
RotateHistory(history, valid_history, HISTORY_QUARTER, cur_month);
|
||||||
|
RotateHistory(history, valid_history, HISTORY_YEAR, cur_month);
|
||||||
|
history.front() = {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an average value for the previous month, as reset for the next month.
|
* Get an average value for the previous month, as reset for the next month.
|
||||||
* @param total Accrued total to average. Will be reset to zero.
|
* @param total Accrued total to average. Will be reset to zero.
|
||||||
|
@ -68,17 +71,6 @@ T GetAndResetAccumulatedAverage(Taccrued &total)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get historical data.
|
|
||||||
* @tparam T type of history data element.
|
|
||||||
* @param history History data to extract from.
|
|
||||||
* @param valid_history Mask of valid history records.
|
|
||||||
* @param hr History range to get.
|
|
||||||
* @param age Age of data to get.
|
|
||||||
* @param cur_month Current economy month.
|
|
||||||
* @param[out] result Extracted historical data.
|
|
||||||
* @return True iff the data for this history range and age is valid.
|
|
||||||
*/
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool GetHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint age, T &result)
|
bool GetHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint age, T &result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#ifndef HISTORY_TYPE_HPP
|
#ifndef HISTORY_TYPE_HPP
|
||||||
#define HISTORY_TYPE_HPP
|
#define HISTORY_TYPE_HPP
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
static constexpr uint8_t HISTORY_PERIODS = 24;
|
||||||
|
|
||||||
struct HistoryRange {
|
struct HistoryRange {
|
||||||
const HistoryRange *hr;
|
const HistoryRange *hr;
|
||||||
const uint8_t periods; ///< Number of periods for this range.
|
const uint8_t periods; ///< Number of periods for this range.
|
||||||
|
@ -31,7 +35,6 @@ struct HistoryRange {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr uint8_t HISTORY_PERIODS = 24;
|
|
||||||
static constexpr HistoryRange HISTORY_MONTH{HISTORY_PERIODS};
|
static constexpr HistoryRange HISTORY_MONTH{HISTORY_PERIODS};
|
||||||
static constexpr HistoryRange HISTORY_QUARTER{HISTORY_MONTH, 3, HISTORY_PERIODS};
|
static constexpr HistoryRange HISTORY_QUARTER{HISTORY_MONTH, 3, HISTORY_PERIODS};
|
||||||
static constexpr HistoryRange HISTORY_YEAR{HISTORY_QUARTER, 4, HISTORY_PERIODS};
|
static constexpr HistoryRange HISTORY_YEAR{HISTORY_QUARTER, 4, HISTORY_PERIODS};
|
||||||
|
|
|
@ -368,7 +368,7 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI
|
||||||
next = v->cur_implicit_order_index;
|
next = v->cur_implicit_order_index;
|
||||||
if (next >= this->GetNumOrders()) {
|
if (next >= this->GetNumOrders()) {
|
||||||
next = this->GetFirstOrder();
|
next = this->GetFirstOrder();
|
||||||
if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid();
|
if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid().base();
|
||||||
} else {
|
} else {
|
||||||
/* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list.
|
/* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list.
|
||||||
* As the given "next" is already valid and a station in the list, we
|
* As the given "next" is already valid and a station in the list, we
|
||||||
|
@ -404,11 +404,11 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI
|
||||||
if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) &&
|
if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) &&
|
||||||
orders[next].GetDestination() == v->last_station_visited &&
|
orders[next].GetDestination() == v->last_station_visited &&
|
||||||
(orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
|
(orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
|
||||||
return StationID::Invalid();
|
return StationID::Invalid().base();
|
||||||
}
|
}
|
||||||
} while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited);
|
} while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited);
|
||||||
|
|
||||||
return orders[next].GetDestination().ToStationID();
|
return orders[next].GetDestination().ToStationID().base();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5079,7 +5079,7 @@ StationIDStack FlowStatMap::DeleteFlows(StationID via)
|
||||||
FlowStat &s_flows = f_it->second;
|
FlowStat &s_flows = f_it->second;
|
||||||
s_flows.ChangeShare(via, INT_MIN);
|
s_flows.ChangeShare(via, INT_MIN);
|
||||||
if (s_flows.GetShares()->empty()) {
|
if (s_flows.GetShares()->empty()) {
|
||||||
ret.Push(f_it->first);
|
ret.Push(f_it->first.base());
|
||||||
this->erase(f_it++);
|
this->erase(f_it++);
|
||||||
} else {
|
} else {
|
||||||
++f_it;
|
++f_it;
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct RoadStop;
|
||||||
struct StationSpec;
|
struct StationSpec;
|
||||||
struct Waypoint;
|
struct Waypoint;
|
||||||
|
|
||||||
using StationIDStack = SmallStack<StationID, StationID::BaseType, StationID::Invalid().base(), 8, StationID::End().base()>;
|
using StationIDStack = SmallStack<StationID::BaseType, StationID::BaseType, StationID::Invalid().base(), 8, StationID::End().base()>;
|
||||||
|
|
||||||
/** Station types */
|
/** Station types */
|
||||||
enum class StationType : uint8_t {
|
enum class StationType : uint8_t {
|
||||||
|
|
|
@ -48,8 +48,8 @@ TEST_CASE("History Rotation and Reporting tests")
|
||||||
uint16_t i = 12 * HISTORY_PERIODS;
|
uint16_t i = 12 * HISTORY_PERIODS;
|
||||||
for (uint date = 1; date <= 12 * HISTORY_PERIODS; ++date, --i) {
|
for (uint date = 1; date <= 12 * HISTORY_PERIODS; ++date, --i) {
|
||||||
history[THIS_MONTH] = i;
|
history[THIS_MONTH] = i;
|
||||||
UpdateValidHistory(valid_history, HISTORY_YEAR, date % 12);
|
UpdateValidHistory(valid_history, date % 12);
|
||||||
RotateHistory(history, valid_history, HISTORY_YEAR, date % 12);
|
RotateHistory(history, valid_history, date % 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* With the decreasing sequence, the expected value is triangle number (x*x+n)/2 and the square of the total divisions.
|
/* With the decreasing sequence, the expected value is triangle number (x*x+n)/2 and the square of the total divisions.
|
||||||
|
|
|
@ -741,7 +741,7 @@ public:
|
||||||
*/
|
*/
|
||||||
inline StationIDStack GetNextStoppingStation() const
|
inline StationIDStack GetNextStoppingStation() const
|
||||||
{
|
{
|
||||||
return (this->orders == nullptr) ? StationID::Invalid() : this->orders->GetNextStoppingStation(this);
|
return (this->orders == nullptr) ? StationID::Invalid().base() : this->orders->GetNextStoppingStation(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetRefitCaps();
|
void ResetRefitCaps();
|
||||||
|
|
Loading…
Reference in New Issue