00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "forecast.h"
00028
00029 namespace module_forecast
00030 {
00031
00032 const Keyword Forecast::tag_total("total");
00033 const Keyword Forecast::tag_net("net");
00034 const Keyword Forecast::tag_consumed("consumed");
00035
00036
00037 bool Forecast::callback(Calendar* l, const Signal a)
00038 {
00039
00040
00041
00042 for (MapOfForecasts::iterator x = ForecastDictionary.begin();
00043 x != ForecastDictionary.end(); ++x)
00044 if (x->second->calptr == l)
00045
00046 x->second->calptr = NULL;
00047 return true;
00048 }
00049
00050
00051 Forecast::~Forecast()
00052 {
00053
00054 for (MapOfForecasts::iterator x=
00055 ForecastDictionary.lower_bound(make_pair(&*getItem(),&*getCustomer()));
00056 x != ForecastDictionary.end(); ++x)
00057 if (x->second == this)
00058 {
00059 ForecastDictionary.erase(x);
00060 break;
00061 }
00062
00063
00064 for(memberIterator i = beginMember(); i != endMember(); i = beginMember())
00065 delete &*i;
00066 }
00067
00068
00069 void Forecast::initialize()
00070 {
00071 if (!calptr) throw DataException("Missing forecast calendar");
00072
00073
00074
00075 const CalendarDouble* c = dynamic_cast<const CalendarDouble*>(calptr);
00076 ForecastBucket* prev = NULL;
00077 Date prevDate;
00078 double prevValue(0.0);
00079 if (c)
00080
00081 for (CalendarDouble::EventIterator i(c); i.getDate()<=Date::infiniteFuture; ++i)
00082 {
00083 if ((prevDate || i.getDate() == Date::infiniteFuture) && prevValue > 0.0)
00084 {
00085 prev = new ForecastBucket
00086 (this, prevDate, i.getDate(), prevValue, prev);
00087 Demand::add(prev);
00088 }
00089 if (i.getDate() == Date::infiniteFuture) break;
00090 prevDate = i.getDate();
00091 prevValue = i.getValue();
00092 }
00093 else
00094 {
00095 const CalendarInt* c = dynamic_cast<const CalendarInt*>(calptr);
00096 if (c)
00097
00098 for (CalendarInt::EventIterator i(c); i.getDate()<=Date::infiniteFuture; ++i)
00099 {
00100 if ((prevDate || i.getDate() == Date::infiniteFuture) && prevValue > 0)
00101 {
00102 prev = new ForecastBucket
00103 (this, prevDate, i.getDate(), prevValue, prev);
00104 Demand::add(prev);
00105 }
00106 if (i.getDate() == Date::infiniteFuture) break;
00107 prevDate = i.getDate();
00108 prevValue = static_cast<double>(i.getValue());
00109 }
00110 else
00111 {
00112 const CalendarBool* c = dynamic_cast<const CalendarBool*>(calptr);
00113 bool prevValueBool = false;
00114 if (c)
00115
00116 for (CalendarBool::EventIterator i(c); true; ++i)
00117 {
00118 if ((prevDate || i.getDate() == Date::infiniteFuture) && prevValueBool)
00119 {
00120 prev = new ForecastBucket
00121 (this, prevDate, i.getDate(), 1.0, prev);
00122 Demand::add(prev);
00123 }
00124 if (i.getDate() == Date::infiniteFuture) break;
00125 prevDate = i.getDate();
00126 prevValueBool = i.getValue();
00127 }
00128 else
00129 {
00130
00131 for (Calendar::EventIterator i(calptr); true; ++i)
00132 {
00133 if (prevDate || i.getDate() == Date::infiniteFuture)
00134 {
00135 prev = new ForecastBucket(this, prevDate, i.getDate(), 1.0, prev);
00136 Demand::add(prev);
00137 if (i.getDate() == Date::infiniteFuture) break;
00138 }
00139 prevDate = i.getDate();
00140 }
00141 }
00142 }
00143 }
00144 }
00145
00146
00147 void Forecast::setDiscrete(const bool b)
00148 {
00149
00150 discrete = b;
00151
00152
00153 if (discrete)
00154 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00155 m->setQuantity(floor(m->getQuantity()));
00156 }
00157
00158
00159 void Forecast::setTotalQuantity(const DateRange& d, double f)
00160 {
00161
00162 if (!isGroup()) initialize();
00163
00164
00165 double weights = 0.0;
00166 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00167 {
00168 ForecastBucket* x = dynamic_cast<ForecastBucket*>(&*m);
00169 if (!x)
00170 throw DataException("Invalid subdemand of forecast '" + getName() +"'");
00171 if (d.intersect(x->getDueRange()))
00172 {
00173
00174 if (!d.getDuration())
00175 {
00176
00177 x->setTotal(f);
00178 return;
00179 }
00180 weights += x->getWeight() * static_cast<long>(x->getDueRange().overlap(d));
00181 }
00182 }
00183
00184
00185 if (!weights)
00186 throw DataException("No valid forecast date in range "
00187 + string(d) + " of forecast '" + getName() +"'");
00188
00189
00190 f /= weights;
00191 double carryover = 0.0;
00192 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00193 {
00194 ForecastBucket* x = dynamic_cast<ForecastBucket*>(&*m);
00195 if (d.intersect(x->getDueRange()))
00196 {
00197
00198 TimePeriod o = x->getDueRange().overlap(d);
00199 double percent = x->getWeight() * static_cast<long>(o);
00200 if (getDiscrete())
00201 {
00202
00203 carryover += f * percent;
00204 int intdelta = static_cast<int>(ceil(carryover - 0.5));
00205 carryover -= intdelta;
00206 if (o < x->getDueRange().getDuration())
00207
00208 x->incTotal(static_cast<double>(intdelta));
00209 else
00210
00211 x->setTotal(static_cast<double>(intdelta));
00212 }
00213 else
00214 {
00215
00216 if (o < x->getDueRange().getDuration())
00217
00218 x->incTotal(f * percent);
00219 else
00220
00221 x->setTotal(f * percent);
00222 }
00223 }
00224 }
00225 }
00226
00227
00228 void Forecast::writeElement(XMLOutput *o, const Keyword &tag, mode m) const
00229 {
00230
00231 if (m == REFERENCE)
00232 {
00233 o->writeElement
00234 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00235 return;
00236 }
00237
00238
00239 if (m != NOHEADER) o->BeginObject
00240 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00241
00242 o->writeElement(Tags::tag_item, &*getItem());
00243 if (getPriority()) o->writeElement(Tags::tag_priority, getPriority());
00244 o->writeElement(Tags::tag_calendar, calptr);
00245 if (!getDiscrete()) o->writeElement(Tags::tag_discrete, getDiscrete());
00246 o->writeElement(Tags::tag_operation, &*getOperation());
00247
00248
00249 o->BeginObject (Tags::tag_buckets);
00250 for (memberIterator i = beginMember(); i != endMember(); ++i)
00251 {
00252 ForecastBucket* f = dynamic_cast<ForecastBucket*>(&*i);
00253 o->BeginObject(Tags::tag_bucket, Tags::tag_start, string(f->getDue()));
00254 o->writeElement(tag_total, f->getTotal());
00255 o->writeElement(Tags::tag_quantity, f->getQuantity());
00256 o->writeElement(tag_consumed, f->getConsumed());
00257 o->EndObject(Tags::tag_bucket);
00258 }
00259 o->EndObject(Tags::tag_buckets);
00260
00261 o->EndObject(tag);
00262 }
00263
00264
00265 void Forecast::endElement(XMLInput& pIn, const Attribute& pAttr, const DataElement& pElement)
00266 {
00267
00268
00269
00270 if (pAttr.isA(Tags::tag_calendar))
00271 {
00272 Calendar *b = dynamic_cast<Calendar*>(pIn.getPreviousObject());
00273 if (b) setCalendar(b);
00274 else throw LogicException("Incorrect object type during read operation");
00275 }
00276 else if (pAttr.isA(Tags::tag_discrete))
00277 setDiscrete(pElement.getBool());
00278 else if (pAttr.isA(Tags::tag_bucket))
00279 {
00280 pair<DateRange,double> *d =
00281 static_cast< pair<DateRange,double>* >(pIn.getUserArea());
00282 if (d)
00283 {
00284
00285 setTotalQuantity(d->first, d->second);
00286
00287 d->first.setStart(Date());
00288 d->first.setEnd(Date());
00289 d->second = 0;
00290 }
00291 }
00292 else if (pIn.getParentElement().first.isA(Tags::tag_bucket))
00293 {
00294 pair<DateRange,double> *d =
00295 static_cast< pair<DateRange,double>* >(pIn.getUserArea());
00296 if (pAttr.isA(tag_total))
00297 {
00298 if (d) d->second = pElement.getDouble();
00299 else pIn.setUserArea(
00300 new pair<DateRange,double>(DateRange(),pElement.getDouble())
00301 );
00302 }
00303 else if (pAttr.isA(Tags::tag_start))
00304 {
00305 Date x = pElement.getDate();
00306 if (d)
00307 {
00308 if (!d->first.getStart()) d->first.setStartAndEnd(x,x);
00309 else d->first.setStart(x);
00310 }
00311 else pIn.setUserArea(new pair<DateRange,double>(DateRange(x,x),0));
00312 }
00313 else if (pAttr.isA(Tags::tag_end))
00314 {
00315 Date x = pElement.getDate();
00316 if (d)
00317 {
00318 if (!d->first.getStart()) d->first.setStartAndEnd(x,x);
00319 else d->first.setEnd(x);
00320 }
00321 else pIn.setUserArea(new pair<DateRange,double>(DateRange(x,x),0));
00322 }
00323 }
00324 else
00325 Demand::endElement(pIn, pAttr, pElement);
00326
00327 if (pIn.isObjectEnd())
00328 {
00329
00330 if (pIn.getUserArea())
00331 delete static_cast< pair<DateRange,double>* >(pIn.getUserArea());
00332 }
00333 }
00334
00335
00336 void Forecast::beginElement(XMLInput& pIn, const Attribute& pAttr)
00337 {
00338 if (pAttr.isA(Tags::tag_calendar))
00339 pIn.readto( Calendar::reader(Calendar::metadata, pIn.getAttributes()) );
00340 else
00341 Demand::beginElement(pIn, pAttr);
00342 }
00343
00344
00345 void Forecast::setCalendar(Calendar* c)
00346 {
00347 if (isGroup())
00348 throw DataException(
00349 "Changing the calendar of an initialized forecast isn't allowed");
00350 calptr = c;
00351 }
00352
00353
00354 void Forecast::setItem(Item* i)
00355 {
00356
00357 if (getItem() == i) return;
00358
00359
00360 for (MapOfForecasts::iterator x =
00361 ForecastDictionary.lower_bound(make_pair(
00362 &*getItem(),&*getCustomer()
00363 ));
00364 x != ForecastDictionary.end(); ++x)
00365 if (x->second == this)
00366 {
00367 ForecastDictionary.erase(x);
00368 break;
00369 }
00370 ForecastDictionary.insert(make_pair(make_pair(i,&*getCustomer()),this));
00371
00372
00373 Demand::setItem(i);
00374
00375
00376 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00377 m->setItem(i);
00378 }
00379
00380
00381 void Forecast::setCustomer(Customer* i)
00382 {
00383
00384 if (getCustomer() == i) return;
00385
00386
00387 for (MapOfForecasts::iterator x =
00388 ForecastDictionary.lower_bound(make_pair(
00389 getItem(), getCustomer()
00390 ));
00391 x != ForecastDictionary.end(); ++x)
00392 if (x->second == this)
00393 {
00394 ForecastDictionary.erase(x);
00395 break;
00396 }
00397 ForecastDictionary.insert(make_pair(make_pair(&*getItem(),i),this));
00398
00399
00400 Demand::setCustomer(i);
00401
00402
00403 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00404 m->setCustomer(i);
00405 }
00406
00407
00408 void Forecast::setMaxLateness(TimePeriod i)
00409 {
00410 Demand::setMaxLateness(i);
00411
00412 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00413 m->setMaxLateness(i);
00414 }
00415
00416
00417 void Forecast::setMinShipment(double i)
00418 {
00419 Demand::setMinShipment(i);
00420
00421 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00422 m->setMinShipment(i);
00423 }
00424
00425
00426 void Forecast::setPriority(int i)
00427 {
00428 Demand::setPriority(i);
00429
00430 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00431 m->setPriority(i);
00432 }
00433
00434
00435 void Forecast::setOperation(Operation *o)
00436 {
00437 Demand::setOperation(o);
00438
00439 for (memberIterator m = beginMember(); m!=endMember(); ++m)
00440 m->setOperation(o);
00441 }
00442
00443 }