problems_operationplan.cpp
Go to the documentation of this file.00001 /*************************************************************************** 00002 file : $URL: https://frepple.svn.sourceforge.net/svnroot/frepple/trunk/src/model/problems_operationplan.cpp $ 00003 version : $LastChangedRevision: 725 $ $LastChangedBy: jdetaeye $ 00004 date : $LastChangedDate: 2008-04-01 17:25:28 +0200 (Tue, 01 Apr 2008) $ 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * Copyright (C) 2007 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA * 00024 * * 00025 ***************************************************************************/ 00026 00027 00028 #define FREPPLE_CORE 00029 #include "frepple/model.h" 00030 namespace frepple 00031 { 00032 00033 00034 DECLARE_EXPORT void Operation::updateProblems() 00035 { 00036 // Find all operationplans, and delegate the problem detection to them 00037 for (OperationPlan *o = first_opplan; o; o = o->next) o->updateProblems(); 00038 } 00039 00040 00041 // 00042 // BEFORECURRENT, BEFOREFENCE, PLANNEDEARLY, PLANNEDLATE 00043 // 00044 00045 00046 void OperationPlan::updateProblems() 00047 { 00048 // A flag for each problem type that may need to be created 00049 bool needsBeforeCurrent(false); 00050 bool needsBeforeFence(false); 00051 bool needsEarly(false); 00052 bool needsLate(false); 00053 00054 // The following categories of operation plans can't have problems: 00055 // - locked opplans 00056 // - opplans having an owner 00057 // - opplans of hidden operations 00058 if (!getOwner() && !getLocked() && getOperation()->getDetectProblems()) 00059 { 00060 // Check if a BeforeCurrent problem is required. 00061 if (dates.getStart() < Plan::instance().getCurrent()) 00062 needsBeforeCurrent = true; 00063 00064 // Check if a BeforeFence problem is required. 00065 // Note that we either detect of beforeCurrent or a beforeFence problem, 00066 // never both simultaneously. 00067 else if 00068 (dates.getStart() < Plan::instance().getCurrent() + oper->getFence()) 00069 needsBeforeFence = true; 00070 00071 // Check if a PlannedEarly problem is required 00072 if (getEpst() 00073 && getDates().getStart() 00074 < getEpst() - ProblemPlannedEarly::getAllowedEarly()) 00075 needsEarly = true; 00076 00077 // Check if a PlannedLate problem is required 00078 if (getLpst() 00079 && getDates().getStart() 00080 > getLpst() + ProblemPlannedLate::getAllowedLate()) 00081 needsLate = true; 00082 } 00083 00084 // Loop through the existing problems 00085 for (Problem::const_iterator j = Problem::begin(this, false); 00086 j!=Problem::end(); ++j) 00087 { 00088 // Need to increment now and define a pointer to the problem, since the 00089 // problem can be deleted soon (which invalidates the iterator). 00090 Problem& curprob = *j; 00091 ++j; 00092 // The if-statement keeps the problem detection code concise and 00093 // concentrated. However, a drawback of this design is that a new problem 00094 // subclass will also require a new demand subclass. I think such a link 00095 // is acceptable. 00096 if (typeid(curprob) == typeid(ProblemBeforeCurrent)) 00097 { 00098 // if: problem needed and it exists already 00099 if (needsBeforeCurrent) needsBeforeCurrent = false; 00100 // else: problem not needed but it exists already 00101 else delete &curprob; 00102 } 00103 else if (typeid(curprob) == typeid(ProblemBeforeFence)) 00104 { 00105 if (needsBeforeFence) needsBeforeFence = false; 00106 else delete &curprob; 00107 } 00108 else if (typeid(curprob) == typeid(ProblemPlannedEarly)) 00109 { 00110 if (needsEarly) needsEarly = false; 00111 else delete &curprob; 00112 } 00113 else if (typeid(curprob) == typeid(ProblemPlannedLate)) 00114 { 00115 if (needsLate) needsLate = false; 00116 else delete &curprob; 00117 } 00118 } 00119 00120 // Create the problems that are required but aren't existing yet. 00121 // There is a little trick involved here... Normally problems are owned 00122 // by objects of the Plannable class. OperationPlan isn't a subclass of 00123 // Plannable, so we need a dirty cast. 00124 if (needsBeforeCurrent) new ProblemBeforeCurrent(this); 00125 if (needsBeforeFence) new ProblemBeforeFence(this); 00126 if (needsEarly) new ProblemPlannedEarly(this); 00127 if (needsLate) new ProblemPlannedLate(this); 00128 } 00129 00130 00131 DECLARE_EXPORT TimePeriod ProblemPlannedEarly::allowedEarly; 00132 DECLARE_EXPORT TimePeriod ProblemPlannedLate::allowedLate; 00133 00134 00135 void ProblemPlannedEarly::setAllowedEarly(TimePeriod p) 00136 { 00137 allowedEarly = p; 00138 00139 // Let all operationplans check for new problems 00140 // Note that ProblemPlannedEarly problems are subscribing to their 00141 // operationplan and the update() method is notifying them. 00142 for (OperationPlan::iterator i = OperationPlan::begin(); 00143 i != OperationPlan::end(); ++i) 00144 i->getOperation()->setChanged(); 00145 } 00146 00147 00148 void ProblemPlannedLate::setAllowedLate(TimePeriod p) 00149 { 00150 allowedLate = p; 00151 00152 // Let all operationplans check for new problems 00153 // Note that ProblemPlannedLate problems are subscribing to their 00154 // operationplan and the update() method is notifying them. 00155 for (OperationPlan::iterator i = OperationPlan::begin(); 00156 i != OperationPlan::end(); ++i) 00157 i->getOperation()->setChanged(); 00158 } 00159 00160 00161 // 00162 // PRECEDENCE 00163 // 00164 00165 00166 void OperationPlanRouting::updateProblems() // @todo test! may well be broken 00167 { 00168 // Make a list of all existing precedence problems 00169 list<ProblemPrecedence*> currentproblems; 00170 for (Problem::const_iterator j = Problem::begin(this, false); 00171 j!=Problem::end(); ++j) 00172 if (typeid(*j) == typeid(ProblemPrecedence)) 00173 currentproblems.push_front(static_cast<ProblemPrecedence*>(&*j)); 00174 00175 // Problem detection: Check for new precedence_before problem 00176 OperationPlan* prev = NULL; 00177 for (list<OperationPlan*>::const_iterator i = step_opplans.begin(); 00178 i != step_opplans.end(); ++i) 00179 { 00180 if (prev && prev->getDates().getEnd() > (*i)->getDates().getStart()) 00181 { 00182 // We need a precedence problem. It could already exist or we need a 00183 // new one... 00184 list<ProblemPrecedence*>::iterator l; 00185 for (l = currentproblems.begin(); l != currentproblems.end(); ++l) 00186 if ((*l)->getFirstOperationPlan() == prev) 00187 { 00188 // It already exists 00189 currentproblems.erase(l); 00190 break; 00191 } 00192 if (l == currentproblems.end()) 00193 // It is a new problem 00194 new ProblemPrecedence (getOperation(), prev, *i); 00195 } 00196 prev = *i; 00197 } 00198 00199 // Erase old problems that have now become obsolete 00200 while (!currentproblems.empty()) 00201 { 00202 delete currentproblems.front(); 00203 currentproblems.pop_front(); 00204 } 00205 00206 // Continue with the normal problem detection 00207 OperationPlan::updateProblems(); 00208 } 00209 00210 }
Documentation generated by
