# cargopacket.cpp

Go to the documentation of this file.

    00001 /* $Id: cargopacket.cpp 15299 2009-01-31 20:16:06Z smatz $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "station_base.h"
    00007 #include "oldpool_func.h"
    00008
    00009 /* Initialize the cargopacket-pool */
    00010 DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
    00011
    00012 void InitializeCargoPackets()
    00013 {
    00014   /* Clean the cargo packet pool and create 1 block in it */
    00015   _CargoPacket_pool.CleanPool();
    00016   _CargoPacket_pool.AddBlockToPool();
    00017 }
    00018
    00019 CargoPacket::CargoPacket(StationID source, uint16 count)
    00020 {
    00021   if (source != INVALID_STATION) assert(count != 0);
    00022
    00023   this->source          = source;
    00024   this->source_xy       = (source != INVALID_STATION) ? GetStation(source)->xy : 0;
    00025   this->loaded_at_xy    = this->source_xy;
    00026
    00027   this->count           = count;
    00028   this->days_in_transit = 0;
    00029   this->feeder_share    = 0;
    00030   this->paid_for        = false;
    00031 }
    00032
    00033 CargoPacket::~CargoPacket()
    00034 {
    00035   this->count = 0;
    00036 }
    00037
    00038 bool CargoPacket::SameSource(const CargoPacket *cp) const
    00039 {
    00040   return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit && this->paid_for == cp->paid_for;
    00041 }
    00042
    00043 /*
    00044  *
    00045  * Cargo list implementation
    00046  *
    00047  */
    00048
    00049 CargoList::~CargoList()
    00050 {
    00051   while (!packets.empty()) {
    00052     delete packets.front();
    00053     packets.pop_front();
    00054   }
    00055 }
    00056
    00057 const CargoList::List *CargoList::Packets() const
    00058 {
    00059   return &packets;
    00060 }
    00061
    00062 void CargoList::AgeCargo()
    00063 {
    00064   if (empty) return;
    00065
    00066   uint dit = 0;
    00067   for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
    00068     if ((*it)->days_in_transit != 0xFF) (*it)->days_in_transit++;
    00069     dit += (*it)->days_in_transit * (*it)->count;
    00070   }
    00071   days_in_transit = dit / count;
    00072 }
    00073
    00074 bool CargoList::Empty() const
    00075 {
    00076   return empty;
    00077 }
    00078
    00079 uint CargoList::Count() const
    00080 {
    00081   return count;
    00082 }
    00083
    00084 bool CargoList::UnpaidCargo() const
    00085 {
    00086   return unpaid_cargo;
    00087 }
    00088
    00089 Money CargoList::FeederShare() const
    00090 {
    00091   return feeder_share;
    00092 }
    00093
    00094 StationID CargoList::Source() const
    00095 {
    00096   return source;
    00097 }
    00098
    00099 uint CargoList::DaysInTransit() const
    00100 {
    00101   return days_in_transit;
    00102 }
    00103
    00104 void CargoList::Append(CargoPacket *cp)
    00105 {
    00106   assert(cp != NULL);
    00107   assert(cp->IsValid());
    00108
    00109   for (List::iterator it = packets.begin(); it != packets.end(); it++) {
    00110     if ((*it)->SameSource(cp) && (*it)->count + cp->count <= 65535) {
    00111       (*it)->count        += cp->count;
    00112       (*it)->feeder_share += cp->feeder_share;
    00113       delete cp;
    00114
    00115       InvalidateCache();
    00116       return;
    00117     }
    00118   }
    00119
    00120   /* The packet could not be merged with another one */
    00121   packets.push_back(cp);
    00122   InvalidateCache();
    00123 }
    00124
    00125
    00126 void CargoList::Truncate(uint count)
    00127 {
    00128   for (List::iterator it = packets.begin(); it != packets.end(); it++) {
    00129     uint local_count = (*it)->count;
    00130     if (local_count <= count) {
    00131       count -= local_count;
    00132       continue;
    00133     }
    00134
    00135     (*it)->count = count;
    00136     count = 0;
    00137   }
    00138
    00139   while (!packets.empty()) {
    00140     CargoPacket *cp = packets.back();
    00141     if (cp->count != 0) break;
    00142     delete cp;
    00143     packets.pop_back();
    00144   }
    00145
    00146   InvalidateCache();
    00147 }
    00148
    00149 bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, uint data)
    00150 {
    00151   assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
    00152   CargoList tmp;
    00153
    00154   while (!packets.empty() && count > 0) {
    00155     CargoPacket *cp = *packets.begin();
    00156     if (cp->count <= count) {
    00157       /* Can move the complete packet */
    00158       packets.remove(cp);
    00159       switch (mta) {
    00160         case MTA_FINAL_DELIVERY:
    00161           if (cp->source == data) {
    00162             tmp.Append(cp);
    00163           } else {
    00164             count -= cp->count;
    00165             delete cp;
    00166           }
    00167           break;
    00168         case MTA_CARGO_LOAD:
    00169           cp->loaded_at_xy = data;
    00170           /* When cargo is moved into another vehicle you have *always* paid for it */
    00171           cp->paid_for     = false;
    00172           /* FALL THROUGH */
    00173         case MTA_OTHER:
    00174           count -= cp->count;
    00175           dest->packets.push_back(cp);
    00176           break;
    00177       }
    00178     } else {
    00179       /* Can move only part of the packet, so split it into two pieces */
    00180       if (mta != MTA_FINAL_DELIVERY) {
    00181         CargoPacket *cp_new = new CargoPacket();
    00182
    00183         Money fs = cp->feeder_share * count / static_cast<uint>(cp->count);
    00184         cp->feeder_share -= fs;
    00185
    00186         cp_new->source          = cp->source;
    00187         cp_new->source_xy       = cp->source_xy;
    00188         cp_new->loaded_at_xy    = (mta == MTA_CARGO_LOAD) ? data : cp->loaded_at_xy;
    00189
    00190         cp_new->days_in_transit = cp->days_in_transit;
    00191         cp_new->feeder_share    = fs;
    00192         /* When cargo is moved into another vehicle you have *always* paid for it */
    00193         cp_new->paid_for        = (mta == MTA_CARGO_LOAD) ? false : cp->paid_for;
    00194
    00195         cp_new->count = count;
    00196         dest->packets.push_back(cp_new);
    00197       }
    00198       cp->count -= count;
    00199
    00200       count = 0;
    00201     }
    00202   }
    00203
    00204   bool remaining = !packets.empty();
    00205
    00206   if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
    00207     /* There are some packets that could not be delivered at the station, put them back */
    00208     tmp.MoveTo(this, UINT_MAX);
    00209     tmp.packets.clear();
    00210   }
    00211
    00212   if (dest != NULL) dest->InvalidateCache();
    00213   InvalidateCache();
    00214
    00215   return remaining;
    00216 }
    00217
    00218 void CargoList::InvalidateCache()
    00219 {
    00220   empty = packets.empty();
    00221   count = 0;
    00222   unpaid_cargo = false;
    00223   feeder_share = 0;
    00224   source = INVALID_STATION;
    00225   days_in_transit = 0;
    00226
    00227   if (empty) return;
    00228
    00229   uint dit = 0;
    00230   for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
    00231     count        += (*it)->count;
    00232     unpaid_cargo |= !(*it)->paid_for;
    00233     dit          += (*it)->days_in_transit * (*it)->count;
    00234     feeder_share += (*it)->feeder_share;
    00235   }
    00236   days_in_transit = dit / count;
    00237   source = (*packets.begin())->source;
    00238 }
    00239