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 

Generated on Mon May 11 15:48:02 2009 for OpenTTD by  doxygen 1.5.6