cargopacket.cpp

Go to the documentation of this file.
00001 /* $Id: cargopacket.cpp 16742 2009-07-04 17:39:00Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "station_base.h"
00007 #include "oldpool_func.h"
00008 #include "economy_base.h"
00009 
00010 /* Initialize the cargopacket-pool */
00011 DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
00012 
00013 void InitializeCargoPackets()
00014 {
00015   /* Clean the cargo packet pool and create 1 block in it */
00016   _CargoPacket_pool.CleanPool();
00017   _CargoPacket_pool.AddBlockToPool();
00018 }
00019 
00020 CargoPacket::CargoPacket(StationID source, uint16 count)
00021 {
00022   if (source != INVALID_STATION) assert(count != 0);
00023 
00024   this->source          = source;
00025   this->source_xy       = (source != INVALID_STATION) ? GetStation(source)->xy : 0;
00026   this->loaded_at_xy    = this->source_xy;
00027 
00028   this->count           = count;
00029   this->days_in_transit = 0;
00030   this->feeder_share    = 0;
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;
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 Money CargoList::FeederShare() const
00085 {
00086   return feeder_share;
00087 }
00088 
00089 StationID CargoList::Source() const
00090 {
00091   return source;
00092 }
00093 
00094 uint CargoList::DaysInTransit() const
00095 {
00096   return days_in_transit;
00097 }
00098 
00099 void CargoList::Append(CargoPacket *cp)
00100 {
00101   assert(cp != NULL);
00102   assert(cp->IsValid());
00103 
00104   for (List::iterator it = packets.begin(); it != packets.end(); it++) {
00105     if ((*it)->SameSource(cp) && (*it)->count + cp->count <= 65535) {
00106       (*it)->count        += cp->count;
00107       (*it)->feeder_share += cp->feeder_share;
00108       delete cp;
00109 
00110       InvalidateCache();
00111       return;
00112     }
00113   }
00114 
00115   /* The packet could not be merged with another one */
00116   packets.push_back(cp);
00117   InvalidateCache();
00118 }
00119 
00120 
00121 void CargoList::Truncate(uint count)
00122 {
00123   for (List::iterator it = packets.begin(); it != packets.end(); it++) {
00124     uint local_count = (*it)->count;
00125     if (local_count <= count) {
00126       count -= local_count;
00127       continue;
00128     }
00129 
00130     (*it)->count = count;
00131     count = 0;
00132   }
00133 
00134   while (!packets.empty()) {
00135     CargoPacket *cp = packets.back();
00136     if (cp->count != 0) break;
00137     delete cp;
00138     packets.pop_back();
00139   }
00140 
00141   InvalidateCache();
00142 }
00143 
00144 bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, CargoPayment *payment, uint data)
00145 {
00146   assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00147   assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
00148   CargoList tmp;
00149 
00150   while (!packets.empty() && count > 0) {
00151     CargoPacket *cp = *packets.begin();
00152     if (cp->count <= count) {
00153       /* Can move the complete packet */
00154       packets.remove(cp);
00155       switch (mta) {
00156         case MTA_FINAL_DELIVERY:
00157           if (cp->source == data) {
00158             tmp.Append(cp);
00159           } else {
00160             payment->PayFinalDelivery(cp, cp->count);
00161             count -= cp->count;
00162             delete cp;
00163           }
00164           continue; // of the loop
00165 
00166         case MTA_CARGO_LOAD:
00167           cp->loaded_at_xy = data;
00168           break;
00169 
00170         case MTA_TRANSFER:
00171           payment->PayTransfer(cp, cp->count);
00172           break;
00173 
00174         case MTA_UNLOAD:
00175           break;
00176       }
00177       count -= cp->count;
00178       dest->packets.push_back(cp);
00179     } else {
00180       /* Can move only part of the packet, so split it into two pieces */
00181       if (mta != MTA_FINAL_DELIVERY) {
00182         CargoPacket *cp_new = new CargoPacket();
00183 
00184         Money fs = cp->feeder_share * count / static_cast<uint>(cp->count);
00185         cp->feeder_share -= fs;
00186 
00187         cp_new->source          = cp->source;
00188         cp_new->source_xy       = cp->source_xy;
00189         cp_new->loaded_at_xy    = (mta == MTA_CARGO_LOAD) ? data : cp->loaded_at_xy;
00190 
00191         cp_new->days_in_transit = cp->days_in_transit;
00192         cp_new->feeder_share    = fs;
00193 
00194         cp_new->count = count;
00195         dest->packets.push_back(cp_new);
00196 
00197         if (mta == MTA_TRANSFER) payment->PayTransfer(cp_new, count);
00198       } else {
00199         payment->PayFinalDelivery(cp, count);
00200       }
00201       cp->count -= count;
00202 
00203       count = 0;
00204     }
00205   }
00206 
00207   bool remaining = !packets.empty();
00208 
00209   if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
00210     /* There are some packets that could not be delivered at the station, put them back */
00211     tmp.MoveTo(this, UINT_MAX, MTA_UNLOAD, NULL);
00212     tmp.packets.clear();
00213   }
00214 
00215   if (dest != NULL) dest->InvalidateCache();
00216   InvalidateCache();
00217 
00218   return remaining;
00219 }
00220 
00221 void CargoList::InvalidateCache()
00222 {
00223   empty = packets.empty();
00224   count = 0;
00225   feeder_share = 0;
00226   source = INVALID_STATION;
00227   days_in_transit = 0;
00228 
00229   if (empty) return;
00230 
00231   uint dit = 0;
00232   for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
00233     count        += (*it)->count;
00234     dit          += (*it)->days_in_transit * (*it)->count;
00235     feeder_share += (*it)->feeder_share;
00236   }
00237   days_in_transit = dit / count;
00238   source = (*packets.begin())->source;
00239 }
00240 

Generated on Fri Jul 31 22:33:13 2009 for OpenTTD by  doxygen 1.5.6