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 CargoPacket::CargoPacket()
00024 {
00025 this->source_type = ST_INDUSTRY;
00026 this->source_id = INVALID_SOURCE;
00027 }
00028
00040 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
00041 feeder_share(0),
00042 count(count),
00043 days_in_transit(0),
00044 source_id(source_id),
00045 source(source),
00046 source_xy(source_xy),
00047 loaded_at_xy(0)
00048 {
00049 assert(count != 0);
00050 this->source_type = source_type;
00051 }
00052
00067 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) :
00068 feeder_share(feeder_share),
00069 count(count),
00070 days_in_transit(days_in_transit),
00071 source_id(source_id),
00072 source(source),
00073 source_xy(source_xy),
00074 loaded_at_xy(loaded_at_xy)
00075 {
00076 assert(count != 0);
00077 this->source_type = source_type;
00078 }
00079
00085 inline CargoPacket *CargoPacket::Split(uint new_size)
00086 {
00087 if (!CargoPacket::CanAllocateItem()) return NULL;
00088
00089 Money fs = this->feeder_share * new_size / static_cast<uint>(this->count);
00090 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);
00091 this->feeder_share -= fs;
00092 this->count -= new_size;
00093 return cp_new;
00094 }
00095
00100 inline void CargoPacket::Merge(CargoPacket *cp)
00101 {
00102 this->count += cp->count;
00103 this->feeder_share += cp->feeder_share;
00104 delete cp;
00105 }
00106
00112 void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
00113 {
00114 CargoPacket *cp;
00115 FOR_ALL_CARGOPACKETS(cp) {
00116 if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
00117 }
00118 }
00119
00124 void CargoPacket::InvalidateAllFrom(StationID sid)
00125 {
00126 CargoPacket *cp;
00127 FOR_ALL_CARGOPACKETS(cp) {
00128 if (cp->source == sid) cp->source = INVALID_STATION;
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137
00141 template <class Tinst>
00142 CargoList<Tinst>::~CargoList()
00143 {
00144 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
00145 delete *it;
00146 }
00147 }
00148
00153 template <class Tinst>
00154 void CargoList<Tinst>::OnCleanPool()
00155 {
00156 this->packets.clear();
00157 }
00158
00164 template <class Tinst>
00165 void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp)
00166 {
00167 this->count -= cp->count;
00168 this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
00169 }
00170
00176 template <class Tinst>
00177 void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
00178 {
00179 this->count += cp->count;
00180 this->cargo_days_in_transit += cp->days_in_transit * cp->count;
00181 }
00182
00191 template <class Tinst>
00192 void CargoList<Tinst>::Append(CargoPacket *cp)
00193 {
00194 assert(cp != NULL);
00195 static_cast<Tinst *>(this)->AddToCache(cp);
00196
00197 for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
00198 CargoPacket *icp = *it;
00199 if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
00200 icp->Merge(cp);
00201 return;
00202 }
00203 }
00204
00205
00206 this->packets.push_back(cp);
00207 }
00208
00214 template <class Tinst>
00215 void CargoList<Tinst>::Truncate(uint max_remaining)
00216 {
00217 for (Iterator it(packets.begin()); it != packets.end(); ) {
00218 CargoPacket *cp = *it;
00219 if (max_remaining == 0) {
00220
00221 it = this->packets.erase(it);
00222 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00223 delete cp;
00224 continue;
00225 }
00226
00227 uint local_count = cp->count;
00228 if (local_count > max_remaining) {
00229 uint diff = local_count - max_remaining;
00230 this->count -= diff;
00231 this->cargo_days_in_transit -= cp->days_in_transit * diff;
00232 cp->count = max_remaining;
00233 max_remaining = 0;
00234 } else {
00235 max_remaining -= local_count;
00236 }
00237 ++it;
00238 }
00239 }
00240
00262 template <class Tinst>
00263 template <class Tother_inst>
00264 bool CargoList<Tinst>::MoveTo(Tother_inst *dest, uint max_move, MoveToAction mta, CargoPayment *payment, uint data)
00265 {
00266 assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00267 assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
00268
00269 Iterator it(this->packets.begin());
00270 while (it != this->packets.end() && max_move > 0) {
00271 CargoPacket *cp = *it;
00272 if (cp->source == data && mta == MTA_FINAL_DELIVERY) {
00273
00274 ++it;
00275 continue;
00276 }
00277
00278 if (cp->count <= max_move) {
00279
00280 max_move -= cp->count;
00281 it = this->packets.erase(it);
00282 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00283 switch (mta) {
00284 case MTA_FINAL_DELIVERY:
00285 payment->PayFinalDelivery(cp, cp->count);
00286 delete cp;
00287 continue;
00288
00289 case MTA_CARGO_LOAD:
00290 cp->loaded_at_xy = data;
00291 break;
00292
00293 case MTA_TRANSFER:
00294 cp->feeder_share += payment->PayTransfer(cp, cp->count);
00295 break;
00296
00297 case MTA_UNLOAD:
00298 break;
00299 }
00300 dest->Append(cp);
00301 continue;
00302 }
00303
00304
00305 if (mta == MTA_FINAL_DELIVERY) {
00306
00307 payment->PayFinalDelivery(cp, max_move);
00308
00309
00310 uint left = cp->count - max_move;
00311 cp->count = max_move;
00312 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00313
00314
00315
00316 cp->feeder_share = 0;
00317 cp->count = left;
00318 } else {
00319
00320 CargoPacket *cp_new = cp->Split(max_move);
00321
00322
00323 if (cp_new == NULL) return false;
00324
00325 static_cast<Tinst *>(this)->RemoveFromCache(cp_new);
00326
00327 if (mta == MTA_TRANSFER) {
00328
00329 cp_new->feeder_share += payment->PayTransfer(cp_new, max_move);
00330 } else if (mta == MTA_CARGO_LOAD) {
00331 cp_new->loaded_at_xy = data;
00332 }
00333
00334 dest->Append(cp_new);
00335 }
00336
00337 max_move = 0;
00338 }
00339
00340 return it != packets.end();
00341 }
00342
00344 template <class Tinst>
00345 void CargoList<Tinst>::InvalidateCache()
00346 {
00347 this->count = 0;
00348 this->cargo_days_in_transit = 0;
00349
00350 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00351 static_cast<Tinst *>(this)->AddToCache(*it);
00352 }
00353 }
00354
00360 void VehicleCargoList::RemoveFromCache(const CargoPacket *cp)
00361 {
00362 this->feeder_share -= cp->feeder_share;
00363 this->Parent::RemoveFromCache(cp);
00364 }
00365
00371 void VehicleCargoList::AddToCache(const CargoPacket *cp)
00372 {
00373 this->feeder_share += cp->feeder_share;
00374 this->Parent::AddToCache(cp);
00375 }
00376
00380 void VehicleCargoList::AgeCargo()
00381 {
00382 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00383 CargoPacket *cp = *it;
00384
00385 if (cp->days_in_transit == 0xFF) continue;
00386
00387 cp->days_in_transit++;
00388 this->cargo_days_in_transit += cp->count;
00389 }
00390 }
00391
00393 void VehicleCargoList::InvalidateCache()
00394 {
00395 this->feeder_share = 0;
00396 this->Parent::InvalidateCache();
00397 }
00398
00399
00400
00401
00402 template class CargoList<VehicleCargoList>;
00403 template class CargoList<StationCargoList>;
00404
00406 template bool CargoList<VehicleCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00408 template bool CargoList<VehicleCargoList>::MoveTo(StationCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00410 template bool CargoList<StationCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);