cargopacket.cpp
Go to the documentation of this file.00001
00002
00005 #include "stdafx.h"
00006 #include "station_base.h"
00007 #include "oldpool_func.h"
00008 #include "economy_base.h"
00009
00010
00011 DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
00012
00013 void InitializeCargoPackets()
00014 {
00015
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
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
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
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;
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
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
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