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
00033 bool ForecastSolver::callback(Demand* l, const Signal a)
00034 {
00035
00036 solve(l, NULL);
00037
00038
00039 return true;
00040 }
00041
00042
00043 void ForecastSolver::writeElement(XMLOutput *o, const Keyword& tag, mode m) const
00044 {
00045
00046 if (m == REFERENCE)
00047 {
00048 o->writeElement
00049 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00050 return;
00051 }
00052
00053
00054 if (m != NOHEADER) o->BeginObject
00055 (tag, Tags::tag_name, getName(), Tags::tag_type, getType().type);
00056
00057
00058 Solver::writeElement(o, tag, NOHEADER);
00059 }
00060
00061
00062 void ForecastSolver::solve(const Demand* l, void* v)
00063 {
00064
00065 if (!l || dynamic_cast<const Forecast*>(l) || l->getHidden()) return;
00066
00067
00068 if (getLogLevel()>0)
00069 logger << " Netting of demand '" << l << "' ('" << l->getCustomer()
00070 << "','" << l->getItem() << "', '" << l->getDeliveryOperation()
00071 << "'): " << l->getDue() << ", " << l->getQuantity() << endl;
00072
00073
00074 Forecast *fcst = matchDemandToForecast(l);
00075
00076 if (!fcst)
00077 {
00078
00079 if (getLogLevel()>0)
00080 logger << " No matching forecast available" << endl;
00081 return;
00082 }
00083 else if (getLogLevel()>0)
00084 logger << " Matching forecast: " << fcst << endl;
00085
00086
00087 netDemandFromForecast(l,fcst);
00088 }
00089
00090
00091 void ForecastSolver::solve(void *v)
00092 {
00093
00094
00095 sortedDemandList l;
00096 for (Demand::iterator i = Demand::begin(); i != Demand::end(); ++i)
00097
00098 if (!dynamic_cast<Forecast*>(&*i)
00099 && !dynamic_cast<ForecastBucket*>(&*i))
00100 l.insert(&*i);
00101
00102
00103 for(sortedDemandList::iterator i = l.begin(); i != l.end(); ++i)
00104 try {solve(*i, NULL);}
00105 catch (...)
00106 {
00107
00108 logger << "Error: Caught an exception while netting demand '"
00109 << (*i)->getName() << "':" << endl;
00110 try { throw; }
00111 catch (bad_exception&) {logger << " bad exception" << endl;}
00112 catch (exception& e) {logger << " " << e.what() << endl;}
00113 catch (...) {logger << " Unknown type" << endl;}
00114 }
00115 }
00116
00117
00118 Forecast* ForecastSolver::matchDemandToForecast(const Demand* l)
00119 {
00120 pair<const Item*, const Customer*> key
00121 = make_pair(&*(l->getItem()), &*(l->getCustomer()));
00122
00123 do
00124 {
00125 do
00126 {
00127 Forecast::MapOfForecasts::iterator x = Forecast::ForecastDictionary.lower_bound(key);
00128
00129
00130 while (x != Forecast::ForecastDictionary.end() && x->first == key)
00131 {
00132 if (!Forecast::getMatchUsingDeliveryOperation()
00133 || x->second->getDeliveryOperation() == l->getDeliveryOperation())
00134
00135 return x->second;
00136 else
00137 ++ x;
00138 }
00139
00140 if (Forecast::Customer_Then_Item_Hierarchy)
00141 {
00142
00143 if (key.second) key.second = key.second->getOwner();
00144 else break;
00145 }
00146 else
00147 {
00148
00149 if (key.first) key.first = key.first->getOwner();
00150 else break;
00151 }
00152 }
00153 while (true);
00154
00155
00156
00157
00158 if (Forecast::Customer_Then_Item_Hierarchy)
00159 {
00160
00161 if (key.first) key.first = key.first->getOwner();
00162 else return NULL;
00163
00164 key.second = &*(l->getCustomer());
00165 }
00166 else
00167 {
00168
00169 if (key.second) key.second = key.second->getOwner();
00170 else return NULL;
00171
00172 key.first = &*(l->getItem());
00173 }
00174 }
00175 while (true);
00176 }
00177
00178
00179 void ForecastSolver::netDemandFromForecast(const Demand* dmd, Forecast* fcst)
00180 {
00181
00182 ForecastBucket* zerobucket = NULL;
00183 for (Forecast::memberIterator i = fcst->beginMember(); i != fcst->endMember(); ++i)
00184 {
00185 zerobucket = dynamic_cast<ForecastBucket*>(&*i);
00186 if (zerobucket && zerobucket->getDueRange().within(dmd->getDue())) break;
00187 }
00188 if (!zerobucket)
00189 throw LogicException("Can't find forecast bucket for "
00190 + string(dmd->getDue()) + " in forecast '" + fcst->getName() + "'");
00191
00192
00193 double remaining = dmd->getQuantity();
00194 ForecastBucket* curbucket = zerobucket;
00195 bool backward = true;
00196 while ( remaining > 0 && curbucket
00197 && (dmd->getDue()-Forecast::getNetEarly() < curbucket->getDueRange().getEnd())
00198 && (dmd->getDue()+Forecast::getNetLate() >= curbucket->getDueRange().getStart())
00199 )
00200 {
00201
00202 double available = curbucket->getQuantity();
00203 if (available > 0)
00204 {
00205 if (available >= remaining)
00206 {
00207
00208 if (getLogLevel()>=2)
00209 logger << " Consuming " << remaining << " from bucket "
00210 << curbucket->getDueRange() << " (" << available
00211 << " available)" << endl;
00212 curbucket->incConsumed(remaining);
00213 remaining = 0;
00214 }
00215 else
00216 {
00217
00218 if (getLogLevel()>=2)
00219 logger << " Consuming " << available << " from bucket "
00220 << curbucket->getDueRange() << " (" << available
00221 << " available)" << endl;
00222 remaining -= available;
00223 curbucket->incConsumed(available);
00224 }
00225 }
00226 else if (getLogLevel()>=2)
00227 logger << " Nothing available in bucket "
00228 << curbucket->getDueRange() << endl;
00229
00230
00231 if (backward)
00232 {
00233
00234 curbucket = curbucket->getPreviousBucket();
00235 if (!curbucket)
00236 {
00237 backward = false;
00238 curbucket = zerobucket->getNextBucket();
00239 }
00240 }
00241 else
00242
00243 curbucket = curbucket->getNextBucket();
00244 }
00245
00246
00247 if (remaining > 0 && getLogLevel()>=2)
00248 logger << " Remains " << remaining << " that can't be netted" << endl;
00249
00250 }
00251
00252 }