diff options
author | fonsinchen <fonsinchen@openttd.org> | 2014-09-21 16:20:48 +0000 |
---|---|---|
committer | fonsinchen <fonsinchen@openttd.org> | 2014-09-21 16:20:48 +0000 |
commit | 2128f1e92906563fc7237b8a43f6fa723de70e7c (patch) | |
tree | e24003162545fddee51081d131c0232acc997765 /src/script/api/script_stationlist.cpp | |
parent | 73d273ffd63d809234c6fa5744d13e520e3e480b (diff) | |
download | openttd-2128f1e92906563fc7237b8a43f6fa723de70e7c.tar.xz |
(svn r26893) -Feature: ScriptStationList_Cargo for sorting cargo by from and via
Diffstat (limited to 'src/script/api/script_stationlist.cpp')
-rw-r--r-- | src/script/api/script_stationlist.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/script/api/script_stationlist.cpp b/src/script/api/script_stationlist.cpp index 9d88fd8fc..7467c1a34 100644 --- a/src/script/api/script_stationlist.cpp +++ b/src/script/api/script_stationlist.cpp @@ -12,6 +12,7 @@ #include "../../stdafx.h" #include "script_stationlist.hpp" #include "script_vehicle.hpp" +#include "script_cargo.hpp" #include "../../station_base.h" #include "../../vehicle_base.h" @@ -35,3 +36,240 @@ ScriptStationList_Vehicle::ScriptStationList_Vehicle(VehicleID vehicle_id) if (o->IsType(OT_GOTO_STATION)) this->AddItem(o->GetDestination()); } } + +ScriptStationList_Cargo::ScriptStationList_Cargo(ScriptStationList_Cargo::CargoMode mode, + ScriptStationList_Cargo::CargoSelector selector, StationID station_id, CargoID cargo, + StationID other_station) +{ + switch(mode) { + case CM_WAITING: + ScriptStationList_CargoWaiting(selector, station_id, cargo, other_station).SwapList(this); + break; + case CM_PLANNED: + ScriptStationList_CargoPlanned(selector, station_id, cargo, other_station).SwapList(this); + break; + default: + NOT_REACHED(); + } +} + +ScriptStationList_CargoWaiting::ScriptStationList_CargoWaiting( + ScriptStationList_Cargo::CargoSelector selector, StationID station_id, CargoID cargo, + StationID other_station) +{ + switch(selector) { + case CS_BY_FROM: + ScriptStationList_CargoWaitingByFrom(station_id, cargo).SwapList(this); + break; + case CS_VIA_BY_FROM: + ScriptStationList_CargoWaitingViaByFrom(station_id, cargo, other_station).SwapList(this); + break; + case CS_BY_VIA: + ScriptStationList_CargoWaitingByVia(station_id, cargo).SwapList(this); + break; + case CS_FROM_BY_VIA: + ScriptStationList_CargoWaitingFromByVia(station_id, cargo, other_station).SwapList(this); + break; + default: + NOT_REACHED(); + } +} + +ScriptStationList_CargoPlanned::ScriptStationList_CargoPlanned( + ScriptStationList_Cargo::CargoSelector selector, StationID station_id, CargoID cargo, + StationID other_station) +{ + switch(selector) { + case CS_BY_FROM: + ScriptStationList_CargoPlannedByFrom(station_id, cargo).SwapList(this); + break; + case CS_VIA_BY_FROM: + ScriptStationList_CargoPlannedViaByFrom(station_id, cargo, other_station).SwapList(this); + break; + case CS_BY_VIA: + ScriptStationList_CargoPlannedByVia(station_id, cargo).SwapList(this); + break; + case CS_FROM_BY_VIA: + ScriptStationList_CargoPlannedFromByVia(station_id, cargo, other_station).SwapList(this); + break; + default: + NOT_REACHED(); + } +} + +class CargoCollector { +public: + CargoCollector(ScriptStationList_Cargo *parent, StationID station_id, CargoID cargo, + StationID other); + ~CargoCollector() ; + + template<ScriptStationList_Cargo::CargoSelector Tselector> + void Update(StationID from, StationID via, uint amount); + const GoodsEntry *GE() const { return ge; } + +private: + void SetValue(); + + ScriptStationList_Cargo *list; + const GoodsEntry *ge; + StationID other_station; + + StationID last_key; + uint amount; +}; + +CargoCollector::CargoCollector(ScriptStationList_Cargo *parent, + StationID station_id, CargoID cargo, StationID other) : + list(parent), ge(NULL), other_station(other), last_key(INVALID_STATION), amount(0) +{ + if (!ScriptStation::IsValidStation(station_id)) return; + if (!ScriptCargo::IsValidCargo(cargo)) return; + this->ge = &(Station::Get(station_id)->goods[cargo]); +} + +CargoCollector::~CargoCollector() +{ + this->SetValue(); +} + +void CargoCollector::SetValue() +{ + if (this->amount > 0) { + if (this->list->HasItem(this->last_key)) { + this->list->SetValue(this->last_key, + this->list->GetValue(this->last_key) + this->amount); + } else { + this->list->AddItem(this->last_key, this->amount); + } + } +} + +template<ScriptStationList_Cargo::CargoSelector Tselector> +void CargoCollector::Update(StationID from, StationID via, uint amount) +{ + StationID key = INVALID_STATION; + switch (Tselector) { + case ScriptStationList_Cargo::CS_VIA_BY_FROM: + if (via != this->other_station) return; + /* fall through */ + case ScriptStationList_Cargo::CS_BY_FROM: + key = from; + break; + case ScriptStationList_Cargo::CS_FROM_BY_VIA: + if (from != this->other_station) return; + /* fall through */ + case ScriptStationList_Cargo::CS_BY_VIA: + key = via; + break; + } + if (key == this->last_key) { + this->amount += amount; + } else { + this->SetValue(); + this->amount = amount; + this->last_key = key; + } +} + + +template<ScriptStationList_Cargo::CargoSelector Tselector> +void ScriptStationList_CargoWaiting::Add(StationID station_id, CargoID cargo, StationID other_station) +{ + CargoCollector collector(this, station_id, cargo, other_station); + if (collector.GE() == NULL) return; + + StationCargoList::ConstIterator iter = collector.GE()->cargo.Packets()->begin(); + StationCargoList::ConstIterator end = collector.GE()->cargo.Packets()->end(); + for (; iter != end; ++iter) { + collector.Update<Tselector>((*iter)->SourceStation(), iter.GetKey(), (*iter)->Count()); + } +} + + +template<ScriptStationList_Cargo::CargoSelector Tselector> +void ScriptStationList_CargoPlanned::Add(StationID station_id, CargoID cargo, StationID other_station) +{ + CargoCollector collector(this, station_id, cargo, other_station); + if (collector.GE() == NULL) return; + + FlowStatMap::const_iterator iter = collector.GE()->flows.begin(); + FlowStatMap::const_iterator end = collector.GE()->flows.end(); + for (; iter != end; ++iter) { + const FlowStat::SharesMap *shares = iter->second.GetShares(); + uint prev = 0; + for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin(); + flow_iter != shares->end(); ++flow_iter) { + collector.Update<Tselector>(iter->first, flow_iter->second, flow_iter->first - prev); + prev = flow_iter->first; + } + } +} + +ScriptStationList_CargoWaitingByFrom::ScriptStationList_CargoWaitingByFrom(StationID station_id, + CargoID cargo) +{ + this->Add<CS_BY_FROM>(station_id, cargo); +} + +ScriptStationList_CargoWaitingViaByFrom::ScriptStationList_CargoWaitingViaByFrom( + StationID station_id, CargoID cargo, StationID via) +{ + CargoCollector collector(this, station_id, cargo, via); + if (collector.GE() == NULL) return; + + std::pair<StationCargoList::ConstIterator, StationCargoList::ConstIterator> range = + collector.GE()->cargo.Packets()->equal_range(via); + for (StationCargoList::ConstIterator iter = range.first; iter != range.second; ++iter) { + collector.Update<CS_VIA_BY_FROM>((*iter)->SourceStation(), iter.GetKey(), (*iter)->Count()); + } +} + + +ScriptStationList_CargoWaitingByVia::ScriptStationList_CargoWaitingByVia(StationID station_id, + CargoID cargo) +{ + this->Add<CS_BY_VIA>(station_id, cargo); +} + +ScriptStationList_CargoWaitingFromByVia::ScriptStationList_CargoWaitingFromByVia( + StationID station_id, CargoID cargo, StationID from) +{ + this->Add<CS_FROM_BY_VIA>(station_id, cargo, from); +} + +ScriptStationList_CargoPlannedByFrom::ScriptStationList_CargoPlannedByFrom(StationID station_id, + CargoID cargo) +{ + this->Add<CS_BY_FROM>(station_id, cargo); +} + +ScriptStationList_CargoPlannedViaByFrom::ScriptStationList_CargoPlannedViaByFrom( + StationID station_id, CargoID cargo, StationID via) +{ + this->Add<CS_VIA_BY_FROM>(station_id, cargo, via); +} + + +ScriptStationList_CargoPlannedByVia::ScriptStationList_CargoPlannedByVia(StationID station_id, + CargoID cargo) +{ + this->Add<CS_BY_VIA>(station_id, cargo); +} + + +ScriptStationList_CargoPlannedFromByVia::ScriptStationList_CargoPlannedFromByVia( + StationID station_id, CargoID cargo, StationID from) +{ + CargoCollector collector(this, station_id, cargo, from); + if (collector.GE() == NULL) return; + + FlowStatMap::const_iterator iter = collector.GE()->flows.find(from); + if (iter == collector.GE()->flows.end()) return; + const FlowStat::SharesMap *shares = iter->second.GetShares(); + uint prev = 0; + for (FlowStat::SharesMap::const_iterator flow_iter = shares->begin(); + flow_iter != shares->end(); ++flow_iter) { + collector.Update<CS_FROM_BY_VIA>(iter->first, flow_iter->second, flow_iter->first - prev); + prev = flow_iter->first; + } +} |