loadplan.cpp
Go to the documentation of this file.00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/loadplan.cpp $ 00003 version : $LastChangedRevision: 1315 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2010-07-17 18:08:53 +0200 (Sat, 17 Jul 2010) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007-2010 by Johan De Taeye * 00010 * * 00011 * This library is free software; you can redistribute it and/or modify it * 00012 * under the terms of the GNU Lesser General Public License as published * 00013 * by the Free Software Foundation; either version 2.1 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * 00019 * General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,* 00024 * USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 #define FREPPLE_CORE 00029 #include "frepple/model.h" 00030 00031 namespace frepple 00032 { 00033 00034 DECLARE_EXPORT const MetaCategory* LoadPlan::metadata; 00035 00036 00037 int LoadPlan::initialize() 00038 { 00039 // Initialize the metadata 00040 metadata = new MetaCategory("loadplan", "loadplans"); 00041 00042 // Initialize the Python type 00043 PythonType& x = FreppleCategory<LoadPlan>::getType(); 00044 x.setName("loadplan"); 00045 x.setDoc("frePPLe loadplan"); 00046 x.supportgetattro(); 00047 const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object(); 00048 return x.typeReady(); 00049 } 00050 00051 00052 DECLARE_EXPORT LoadPlan::LoadPlan(OperationPlan *o, const Load *r) 00053 { 00054 assert(o); 00055 ld = const_cast<Load*>(r); 00056 oper = o; 00057 start_or_end = START; 00058 00059 // Add to the operationplan 00060 nextLoadPlan = NULL; 00061 if (o->firstloadplan) 00062 { 00063 // Append to the end 00064 LoadPlan *c = o->firstloadplan; 00065 while (c->nextLoadPlan) c = c->nextLoadPlan; 00066 c->nextLoadPlan = this; 00067 } 00068 else 00069 // First in the list 00070 o->firstloadplan = this; 00071 00072 // Insert in the resource timeline 00073 r->getResource()->loadplans.insert( 00074 this, 00075 ld->getLoadplanQuantity(this), 00076 ld->getLoadplanDate(this) 00077 ); 00078 00079 // Initialize the Python type 00080 initType(metadata); 00081 00082 // Create a loadplan to mark the end of the operationplan. 00083 new LoadPlan(o, r, this); 00084 00085 // Mark the operation and resource as being changed. This will trigger 00086 // the recomputation of their problems 00087 r->getResource()->setChanged(); 00088 r->getOperation()->setChanged(); 00089 } 00090 00091 00092 DECLARE_EXPORT LoadPlan::LoadPlan(OperationPlan *o, const Load *r, LoadPlan *lp) 00093 { 00094 ld = const_cast<Load*>(r); 00095 oper = o; 00096 start_or_end = END; 00097 00098 // Add to the operationplan 00099 nextLoadPlan = NULL; 00100 if (o->firstloadplan) 00101 { 00102 // Append to the end 00103 LoadPlan *c = o->firstloadplan; 00104 while (c->nextLoadPlan) c = c->nextLoadPlan; 00105 c->nextLoadPlan = this; 00106 } 00107 else 00108 // First in the list 00109 o->firstloadplan = this; 00110 00111 // Insert in the resource timeline 00112 r->getResource()->loadplans.insert( 00113 this, 00114 ld->getLoadplanQuantity(this), 00115 ld->getLoadplanDate(this) 00116 ); 00117 00118 // Initialize the Python type 00119 initType(metadata); 00120 } 00121 00122 00123 DECLARE_EXPORT LoadPlan* LoadPlan::getOtherLoadPlan() const 00124 { 00125 for (LoadPlan *i = oper->firstloadplan; i; i = i->nextLoadPlan) 00126 if (i->ld == ld && i != this) return i; 00127 throw LogicException("No matching loadplan found"); 00128 } 00129 00130 00131 DECLARE_EXPORT void LoadPlan::update() 00132 { 00133 // Update the timeline data structure 00134 ld->getResource()->getLoadPlans().update( 00135 this, 00136 ld->getLoadplanQuantity(this), 00137 ld->getLoadplanDate(this) 00138 ); 00139 00140 // Review adjacent setups 00141 if (!isStart()) ld->getResource()->updateSetups(this); 00142 00143 // Mark the operation and resource as being changed. This will trigger 00144 // the recomputation of their problems 00145 ld->getResource()->setChanged(); 00146 ld->getOperation()->setChanged(); 00147 } 00148 00149 00150 DECLARE_EXPORT const string& LoadPlan::getSetup(bool current) const 00151 { 00152 // This resource has no setupmatrix 00153 static string nosetup; 00154 assert(ld); 00155 if (!ld->getResource()->getSetupMatrix()) return nosetup; 00156 00157 // Current load has a setup 00158 if (!ld->getSetup().empty() && current) return ld->getSetup(); 00159 00160 // Scan earlier setups 00161 for (Resource::loadplanlist::const_iterator i(this); 00162 i != getResource()->getLoadPlans().end(); --i) 00163 { 00164 const LoadPlan* j = dynamic_cast<const LoadPlan*>(&*i); 00165 if (j && !j->getLoad()->getSetup().empty() && (current || j != this)) 00166 return j->getLoad()->getSetup(); 00167 } 00168 00169 // No conversions found - return the original setup 00170 return ld->getResource()->getSetup(); 00171 } 00172 00173 00174 DECLARE_EXPORT LoadPlan::~LoadPlan() 00175 { 00176 ld->getResource()->setChanged(); 00177 LoadPlan *prevldplan = NULL; 00178 if (!isStart() && oper->getOperation() == OperationSetup::setupoperation) 00179 { 00180 for (TimeLine<LoadPlan>::const_iterator i = getResource()->getLoadPlans().begin(isStart() ? getOtherLoadPlan() : this); 00181 i != getResource()->getLoadPlans().end(); --i) 00182 { 00183 const LoadPlan *l = dynamic_cast<const LoadPlan*>(&*i); 00184 if (l && l->getOperationPlan() != getOperationPlan() 00185 && l->getOperationPlan() != getOperationPlan()->getOwner() 00186 && !l->isStart()) 00187 { 00188 prevldplan = const_cast<LoadPlan*>(l); 00189 break; 00190 } 00191 } 00192 if (!prevldplan) 00193 { 00194 for (TimeLine<LoadPlan>::const_iterator i = getResource()->getLoadPlans().begin(isStart() ? getOtherLoadPlan() : this); 00195 i != getResource()->getLoadPlans().end(); ++i) 00196 { 00197 const LoadPlan *l = dynamic_cast<const LoadPlan*>(&*i); 00198 if (l && l->getOperationPlan() != getOperationPlan() 00199 && l->getOperationPlan() != getOperationPlan()->getOwner() 00200 && !l->isStart()) 00201 { 00202 prevldplan = const_cast<LoadPlan*>(l); 00203 break; 00204 } 00205 } 00206 } 00207 } 00208 ld->getResource()->loadplans.erase(this); 00209 if (prevldplan) ld->getResource()->updateSetups(prevldplan); 00210 } 00211 00212 00213 DECLARE_EXPORT void LoadPlan::setLoad(const Load* newld) 00214 { 00215 // No change 00216 if (newld == ld) return; 00217 00218 // Verify the data 00219 if (!newld) throw LogicException("Can't switch to NULL load"); 00220 if (ld && ld->getOperation() != newld->getOperation()) 00221 throw LogicException("Only switching to a load on the same operation is allowed"); 00222 00223 // Mark entities as changed 00224 if (oper) oper->getOperation()->setChanged(); 00225 if (ld) ld->getResource()->setChanged(); 00226 newld->getResource()->setChanged(); 00227 00228 // Update also the setup operationplan 00229 if (oper && oper->getOperation() != OperationSetup::setupoperation) 00230 { 00231 bool oldHasSetup = ld && !ld->getSetup().empty() 00232 && ld->getResource()->getSetupMatrix(); 00233 bool newHasSetup = !newld->getSetup().empty() 00234 && newld->getResource()->getSetupMatrix(); 00235 OperationPlan *setupOpplan = NULL; 00236 if (oldHasSetup) 00237 { 00238 for (OperationPlan::iterator i(oper); i != oper->end(); ++i) 00239 if (i->getOperation() == OperationSetup::setupoperation) 00240 { 00241 setupOpplan = &*i; 00242 break; 00243 } 00244 if (!setupOpplan) oldHasSetup = false; 00245 } 00246 if (oldHasSetup) 00247 { 00248 if (newHasSetup) 00249 { 00250 // Case 1: Both the old and new load require a setup 00251 LoadPlan *setupLdplan = NULL; 00252 for (OperationPlan::LoadPlanIterator j = setupOpplan->beginLoadPlans(); 00253 j != setupOpplan->endLoadPlans(); ++j) 00254 if (j->getLoad() == ld) 00255 { 00256 setupLdplan = &*j; 00257 break; 00258 } 00259 if (!setupLdplan) 00260 throw LogicException("Can't find loadplan on setup operationplan"); 00261 // Update the loadplan 00262 setupLdplan->setLoad(newld); 00263 setupOpplan->setEnd(setupOpplan->getDates().getEnd()); 00264 } 00265 else 00266 { 00267 // Case 2: Delete the old setup which is not required any more 00268 oper->eraseSubOperationPlan(setupOpplan); 00269 } 00270 } 00271 else 00272 { 00273 if (newHasSetup) 00274 { 00275 // Case 3: Create a new setup operationplan 00276 OperationSetup::setupoperation->createOperationPlan( 00277 1, Date::infinitePast, oper->getDates().getEnd(), NULL, oper); 00278 } 00279 //else: 00280 // Case 4: No setup for the old or new load 00281 } 00282 } 00283 00284 // Find the loadplan before the setup 00285 LoadPlan *prevldplan = NULL; 00286 if (getOperationPlan()->getOperation() == OperationSetup::setupoperation) 00287 { 00288 for (TimeLine<LoadPlan>::const_iterator i = getResource()->getLoadPlans().begin(isStart() ? getOtherLoadPlan() : this); 00289 i != getResource()->getLoadPlans().end(); --i) 00290 { 00291 const LoadPlan *l = dynamic_cast<const LoadPlan*>(&*i); 00292 if (l && l->getOperationPlan() != getOperationPlan() 00293 && l->getOperationPlan() != getOperationPlan()->getOwner() 00294 && !l->isStart()) 00295 { 00296 prevldplan = const_cast<LoadPlan*>(l); 00297 break; 00298 } 00299 } 00300 if (!prevldplan) 00301 { 00302 for (TimeLine<LoadPlan>::const_iterator i = getResource()->getLoadPlans().begin(isStart() ? getOtherLoadPlan() : this); 00303 i != getResource()->getLoadPlans().end(); ++i) 00304 { 00305 const LoadPlan *l = dynamic_cast<const LoadPlan*>(&*i); 00306 if (l && l->getOperationPlan() != getOperationPlan() 00307 && l->getOperationPlan() != getOperationPlan()->getOwner() 00308 && !l->isStart()) 00309 { 00310 prevldplan = const_cast<LoadPlan*>(l); 00311 break; 00312 } 00313 } 00314 } 00315 } 00316 00317 // Change this loadplan and its brother 00318 for (LoadPlan *ldplan = getOtherLoadPlan(); true; ) 00319 { 00320 // Remove from the old resource, if there is one 00321 if (ldplan->ld) 00322 ldplan->ld->getResource()->loadplans.erase(ldplan); 00323 00324 // Insert in the new resource 00325 ldplan->ld = newld; 00326 newld->getResource()->loadplans.insert( 00327 ldplan, 00328 newld->getLoadplanQuantity(ldplan), 00329 newld->getLoadplanDate(ldplan) 00330 ); 00331 00332 // Repeat for the brother loadplan or exit 00333 if (ldplan != this) ldplan = this; 00334 else break; 00335 } 00336 00337 // Update the setups on the old resource 00338 if (prevldplan) 00339 prevldplan->ld->getResource()->updateSetups(prevldplan); 00340 } 00341 00342 00343 PyObject* LoadPlan::getattro(const Attribute& attr) 00344 { 00345 if (attr.isA(Tags::tag_operationplan)) 00346 return PythonObject(getOperationPlan()); 00347 if (attr.isA(Tags::tag_quantity)) 00348 return PythonObject(getQuantity()); 00349 if (attr.isA(Tags::tag_startdate)) 00350 return PythonObject(getDate()); 00351 if (attr.isA(Tags::tag_enddate)) 00352 return PythonObject(getOtherLoadPlan()->getDate()); 00353 if (attr.isA(Tags::tag_resource)) 00354 return PythonObject(getLoad()->getResource()); 00355 if (attr.isA(Tags::tag_load)) 00356 return PythonObject(getLoad()); 00357 if (attr.isA(Tags::tag_setup)) 00358 return PythonObject(getSetup()); 00359 return NULL; 00360 } 00361 00362 00363 int LoadPlanIterator::initialize() 00364 { 00365 // Initialize the type 00366 PythonType& x = PythonExtension<LoadPlanIterator>::getType(); 00367 x.setName("loadplanIterator"); 00368 x.setDoc("frePPLe iterator for loadplan"); 00369 x.supportiter(); 00370 return x.typeReady(); 00371 } 00372 00373 00374 PyObject* LoadPlanIterator::iternext() 00375 { 00376 LoadPlan* ld; 00377 if (resource_or_opplan) 00378 { 00379 // Skip zero quantity loadplans and load ends 00380 while (*resiter != res->getLoadPlans().end() && (*resiter)->getQuantity()<=0.0) 00381 ++(*resiter); 00382 if (*resiter == res->getLoadPlans().end()) return NULL; 00383 00384 // Return result 00385 ld = const_cast<LoadPlan*>(static_cast<const LoadPlan*>(&*((*resiter)++))); 00386 } 00387 else 00388 { 00389 while (*opplaniter != opplan->endLoadPlans() && (*opplaniter)->getQuantity()==0.0) 00390 ++(*opplaniter); 00391 if (*opplaniter == opplan->endLoadPlans()) return NULL; 00392 ld = static_cast<LoadPlan*>(&*((*opplaniter)++)); 00393 } 00394 Py_INCREF(ld); 00395 return const_cast<LoadPlan*>(ld); 00396 } 00397 00398 } // end namespace
Documentation generated for frePPLe by
