problems_demand.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/problems_demand.cpp $ 00003 version : $LastChangedRevision: 1505 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2011-08-26 18:55:08 +0200 (Fri, 26 Aug 2011) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007-2011 by Johan De Taeye, frePPLe bvba * 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 00035 DECLARE_EXPORT void Demand::updateProblems() 00036 { 00037 // The relation between the demand and the related problem classes is such 00038 // that the demand object is the only active one. The problem objects are 00039 // fully controlled and managed by the associated demand object. 00040 00041 // A flag for each problem type that may need to be created 00042 bool needsNotPlanned(false); 00043 bool needsEarly(false); 00044 bool needsLate(false); 00045 bool needsShort(false); 00046 bool needsExcess(false); 00047 00048 // Problem detection disabled on this demand 00049 if (!getDetectProblems()) return; 00050 00051 // Check which problems need to be created 00052 if (deli.empty()) 00053 { 00054 // Check if a new ProblemDemandNotPlanned needs to be created 00055 if (getQuantity()>0.0) needsNotPlanned = true; 00056 } 00057 else 00058 { 00059 // Loop through the deliveries 00060 for (OperationPlan_list::iterator i = deli.begin(); i!=deli.end(); ++i) 00061 { 00062 // Check for ProblemLate problem 00063 long d(getDue() - (*i)->getDates().getEnd()); 00064 if (d < 0L) needsLate = true; 00065 // Check for ProblemEarly problem 00066 else if (d > 0L) needsEarly = true; 00067 } 00068 00069 // Check for ProblemShort problem 00070 double plannedqty = getPlannedQuantity(); 00071 if (plannedqty + ROUNDING_ERROR < qty) needsShort = true; 00072 00073 // Check for ProblemExcess Problem 00074 if (plannedqty - ROUNDING_ERROR > qty) needsExcess = true; 00075 } 00076 00077 // Loop through the existing problems 00078 for (Problem::const_iterator j = Problem::begin(this, false); 00079 j!=Problem::end(); ) 00080 { 00081 // Need to increment now and define a pointer to the problem, since the 00082 // problem can be deleted soon (which invalidates the iterator). 00083 Problem& curprob = *j; 00084 ++j; 00085 // The if-statement keeps the problem detection code concise and 00086 // concentrated. However, a drawback of this design is that a new Problem 00087 // subclass will also require a new Demand subclass. I think such a link 00088 // is acceptable. 00089 if (typeid(curprob) == typeid(ProblemEarly)) 00090 { 00091 // if: problem needed and it exists already 00092 if (needsEarly) needsEarly = false; 00093 // else: problem not needed but it exists already 00094 else delete &curprob; 00095 } 00096 else if (typeid(curprob) == typeid(ProblemDemandNotPlanned)) 00097 { 00098 if (needsNotPlanned) needsNotPlanned = false; 00099 else delete &curprob; 00100 } 00101 else if (typeid(curprob) == typeid(ProblemLate)) 00102 { 00103 if (needsLate) needsLate = false; 00104 else delete &curprob; 00105 } 00106 else if (typeid(curprob) == typeid(ProblemShort)) 00107 { 00108 if (needsShort) needsShort = false; 00109 else delete &curprob; 00110 } 00111 else if (typeid(curprob) == typeid(ProblemExcess)) 00112 { 00113 if (needsExcess) needsExcess = false; 00114 else delete &curprob; 00115 } 00116 // Note that there may be other demand exceptions that are not caught in 00117 // this loop. These are problems defined and managed by subclasses. 00118 } 00119 00120 // Create the problems that are required but aren't existing yet. 00121 if (needsNotPlanned) new ProblemDemandNotPlanned(this); 00122 if (needsLate) new ProblemLate(this); 00123 if (needsEarly) new ProblemEarly(this); 00124 if (needsShort) new ProblemShort(this); 00125 if (needsExcess) new ProblemExcess(this); 00126 } 00127 00128 00129 DECLARE_EXPORT string ProblemLate::getDescription() const 00130 { 00131 assert(getDemand() && !getDemand()->getDelivery().empty()); 00132 TimePeriod t(getDemand()->getLatestDelivery()->getDates().getEnd() 00133 - getDemand()->getDue()); 00134 return string("Demand '") + getDemand()->getName() + "' planned " 00135 + string(t) + " after its due date"; 00136 } 00137 00138 00139 DECLARE_EXPORT string ProblemEarly::getDescription() const 00140 { 00141 assert(getDemand() && !getDemand()->getDelivery().empty()); 00142 TimePeriod t(getDemand()->getDue() 00143 - getDemand()->getEarliestDelivery()->getDates().getEnd()); 00144 return string("Demand '") + getDemand()->getName() + "' planned " 00145 + string(t) + " before its due date"; 00146 } 00147 00148 }