00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "core/pool_func.hpp"
00014 #include "economy_base.h"
00015
00016
00017 CargoPacketPool _cargopacket_pool("CargoPacket");
00018 INSTANTIATE_POOL_METHODS(CargoPacket)
00019
00020
00023 void InitializeCargoPackets()
00024 {
00025 _cargopacket_pool.CleanPool();
00026 }
00027
00031 CargoPacket::CargoPacket()
00032 {
00033 this->source_type = ST_INDUSTRY;
00034 this->source_id = INVALID_SOURCE;
00035 }
00036
00048 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
00049 feeder_share(0),
00050 count(count),
00051 days_in_transit(0),
00052 source_id(source_id),
00053 source(source),
00054 source_xy(source_xy),
00055 loaded_at_xy(0)
00056 {
00057 assert(count != 0);
00058 this->source_type = source_type;
00059 }
00060
00075 CargoPacket::CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share, SourceType source_type, SourceID source_id) :
00076 feeder_share(feeder_share),
00077 count(count),
00078 days_in_transit(days_in_transit),
00079 source_id(source_id),
00080 source(source),
00081 source_xy(source_xy),
00082 loaded_at_xy(loaded_at_xy)
00083 {
00084 assert(count != 0);
00085 this->source_type = source_type;
00086 }
00087
00093 FORCEINLINE CargoPacket *CargoPacket::Split(uint new_size)
00094 {
00095 Money fs = this->feeder_share * new_size / static_cast<uint>(this->count);
00096 CargoPacket *cp_new = new CargoPacket(new_size, this->days_in_transit, this->source, this->source_xy, this->loaded_at_xy, fs, this->source_type, this->source_id);
00097 this->feeder_share -= fs;
00098 this->count -= new_size;
00099 return cp_new;
00100 }
00101
00106 FORCEINLINE void CargoPacket::Merge(CargoPacket *cp)
00107 {
00108 this->count += cp->count;
00109 this->feeder_share += cp->feeder_share;
00110 delete cp;
00111 }
00112
00118 void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
00119 {
00120 CargoPacket *cp;
00121 FOR_ALL_CARGOPACKETS(cp) {
00122 if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
00123 }
00124 }
00125
00130 void CargoPacket::InvalidateAllFrom(StationID sid)
00131 {
00132 CargoPacket *cp;
00133 FOR_ALL_CARGOPACKETS(cp) {
00134 if (cp->source == sid) cp->source = INVALID_STATION;
00135 }
00136 }
00137
00138
00139
00140
00141
00142
00143
00147 template <class Tinst>
00148 CargoList<Tinst>::~CargoList()
00149 {
00150 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
00151 delete *it;
00152 }
00153 }
00154
00160 template <class Tinst>
00161 void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp)
00162 {
00163 this->count -= cp->count;
00164 this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
00165 }
00166
00172 template <class Tinst>
00173 void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
00174 {
00175 this->count += cp->count;
00176 this->cargo_days_in_transit += cp->days_in_transit * cp->count;
00177 }
00178
00187 template <class Tinst>
00188 void CargoList<Tinst>::Append(CargoPacket *cp)
00189 {
00190 assert(cp != NULL);
00191 static_cast<Tinst *>(this)->AddToCache(cp);
00192
00193 for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
00194 CargoPacket *icp = *it;
00195 if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
00196 icp->Merge(cp);
00197 return;
00198 }
00199 }
00200
00201
00202 this->packets.push_back(cp);
00203 }
00204
00210 template <class Tinst>
00211 void CargoList<Tinst>::Truncate(uint max_remaining)
00212 {
00213 for (Iterator it(packets.begin()); it != packets.end(); ) {
00214 CargoPacket *cp = *it;
00215 if (max_remaining == 0) {
00216
00217 this->packets.erase(it++);
00218 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00219 delete cp;
00220 continue;
00221 }
00222
00223 uint local_count = cp->count;
00224 if (local_count > max_remaining) {
00225 uint diff = local_count - max_remaining;
00226 this->count -= diff;
00227 this->cargo_days_in_transit -= cp->days_in_transit * diff;
00228 cp->count = max_remaining;
00229 max_remaining = 0;
00230 } else {
00231 max_remaining -= local_count;
00232 }
00233 ++it;
00234 }
00235 }
00236
00258 template <class Tinst>
00259 template <class Tother_inst>
00260 bool CargoList<Tinst>::MoveTo(Tother_inst *dest, uint max_move, MoveToAction mta, CargoPayment *payment, uint data)
00261 {
00262 assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00263 assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
00264
00265 Iterator it(this->packets.begin());
00266 while (it != this->packets.end() && max_move > 0) {
00267 CargoPacket *cp = *it;
00268 if (cp->source == data && mta == MTA_FINAL_DELIVERY) {
00269
00270 ++it;
00271 continue;
00272 }
00273
00274 if (cp->count <= max_move) {
00275
00276 max_move -= cp->count;
00277 this->packets.erase(it++);
00278 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00279 switch(mta) {
00280 case MTA_FINAL_DELIVERY:
00281 payment->PayFinalDelivery(cp, cp->count);
00282 delete cp;
00283 continue;
00284
00285 case MTA_CARGO_LOAD:
00286 cp->loaded_at_xy = data;
00287 break;
00288
00289 case MTA_TRANSFER:
00290 cp->feeder_share += payment->PayTransfer(cp, cp->count);
00291 break;
00292
00293 case MTA_UNLOAD:
00294 break;
00295 }
00296 dest->Append(cp);
00297 continue;
00298 }
00299
00300
00301 if (mta == MTA_FINAL_DELIVERY) {
00302
00303 payment->PayFinalDelivery(cp, max_move);
00304
00305
00306 uint left = cp->count - max_move;
00307 cp->count = max_move;
00308 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00309
00310
00311
00312 cp->feeder_share = 0;
00313 cp->count = left;
00314 } else {
00315
00316 CargoPacket *cp_new = cp->Split(max_move);
00317
00318 static_cast<Tinst *>(this)->RemoveFromCache(cp_new);
00319
00320 if (mta == MTA_TRANSFER) {
00321
00322 cp_new->feeder_share += payment->PayTransfer(cp_new, max_move);
00323 } else if (mta == MTA_CARGO_LOAD) {
00324 cp_new->loaded_at_xy = data;
00325 }
00326
00327 dest->Append(cp_new);
00328 }
00329
00330 max_move = 0;
00331 }
00332
00333 return it != packets.end();
00334 }
00335
00337 template <class Tinst>
00338 void CargoList<Tinst>::InvalidateCache()
00339 {
00340 this->count = 0;
00341 this->cargo_days_in_transit = 0;
00342
00343 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00344 static_cast<Tinst *>(this)->AddToCache(*it);
00345 }
00346 }
00347
00353 void VehicleCargoList::RemoveFromCache(const CargoPacket *cp)
00354 {
00355 this->feeder_share -= cp->feeder_share;
00356 this->Parent::RemoveFromCache(cp);
00357 }
00358
00364 void VehicleCargoList::AddToCache(const CargoPacket *cp)
00365 {
00366 this->feeder_share += cp->feeder_share;
00367 this->Parent::AddToCache(cp);
00368 }
00369
00373 void VehicleCargoList::AgeCargo()
00374 {
00375 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00376 CargoPacket *cp = *it;
00377
00378 if (cp->days_in_transit == 0xFF) continue;
00379
00380 cp->days_in_transit++;
00381 this->cargo_days_in_transit += cp->count;
00382 }
00383 }
00384
00386 void VehicleCargoList::InvalidateCache()
00387 {
00388 this->feeder_share = 0;
00389 this->Parent::InvalidateCache();
00390 }
00391
00392
00393
00394
00395 template class CargoList<VehicleCargoList>;
00396 template class CargoList<StationCargoList>;
00397
00399 template bool CargoList<VehicleCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00401 template bool CargoList<VehicleCargoList>::MoveTo(StationCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00403 template bool CargoList<StationCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);