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