flowplan.cpp
Go to the documentation of this file.
00001 /*************************************************************************** 00002 file : $URL: http://svn.code.sf.net/p/frepple/code/trunk/src/model/flowplan.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 namespace frepple 00030 { 00031 00032 DECLARE_EXPORT const MetaCategory* FlowPlan::metadata; 00033 00034 00035 int FlowPlan::initialize() 00036 { 00037 // Initialize the metadata 00038 metadata = new MetaCategory("flowplan", "flowplans"); 00039 00040 // Initialize the Python type 00041 PythonType& x = FreppleCategory<FlowPlan>::getType(); 00042 x.setName("flowplan"); 00043 x.setDoc("frePPLe flowplan"); 00044 x.supportgetattro(); 00045 const_cast<MetaCategory*>(metadata)->pythonClass = x.type_object(); 00046 return x.typeReady(); 00047 } 00048 00049 00050 DECLARE_EXPORT FlowPlan::FlowPlan (OperationPlan *opplan, const Flow *f) 00051 { 00052 assert(opplan && f); 00053 fl = const_cast<Flow*>(f); 00054 00055 // Initialize the Python type 00056 initType(metadata); 00057 00058 // Link the flowplan to the operationplan 00059 oper = opplan; 00060 nextFlowPlan = NULL; 00061 if (opplan->firstflowplan) 00062 { 00063 // Append to the end 00064 FlowPlan *c = opplan->firstflowplan; 00065 while (c->nextFlowPlan) c = c->nextFlowPlan; 00066 c->nextFlowPlan = this; 00067 } 00068 else 00069 // First in the list 00070 opplan->firstflowplan = this; 00071 00072 // Compute the flowplan quantity 00073 fl->getBuffer()->flowplans.insert( 00074 this, 00075 fl->getFlowplanQuantity(this), 00076 fl->getFlowplanDate(this) 00077 ); 00078 00079 // Mark the operation and buffer as having changed. This will trigger the 00080 // recomputation of their problems 00081 fl->getBuffer()->setChanged(); 00082 fl->getOperation()->setChanged(); 00083 } 00084 00085 00086 DECLARE_EXPORT void FlowPlan::update() 00087 { 00088 // Update the timeline data structure 00089 fl->getBuffer()->flowplans.update( 00090 this, 00091 fl->getFlowplanQuantity(this), 00092 fl->getFlowplanDate(this) 00093 ); 00094 00095 // Mark the operation and buffer as having changed. This will trigger the 00096 // recomputation of their problems 00097 fl->getBuffer()->setChanged(); 00098 fl->getOperation()->setChanged(); 00099 } 00100 00101 00102 DECLARE_EXPORT void FlowPlan::setFlow(const Flow* newfl) 00103 { 00104 // No change 00105 if (newfl == fl) return; 00106 00107 // Verify the data 00108 if (!newfl) throw LogicException("Can't switch to NULL flow"); 00109 00110 // Remove from the old buffer, if there is one 00111 if (fl) 00112 { 00113 if (fl->getOperation() != newfl->getOperation()) 00114 throw LogicException("Only switching to a flow on the same operation is allowed"); 00115 fl->getBuffer()->flowplans.erase(this); 00116 fl->getBuffer()->setChanged(); 00117 } 00118 00119 // Insert in the new buffer 00120 fl = newfl; 00121 fl->getBuffer()->flowplans.insert( 00122 this, 00123 fl->getFlowplanQuantity(this), 00124 fl->getFlowplanDate(this) 00125 ); 00126 fl->getBuffer()->setChanged(); 00127 fl->getOperation()->setChanged(); 00128 } 00129 00130 00131 // Remember that this method only superficially looks like a normal 00132 // writeElement() method. 00133 DECLARE_EXPORT void FlowPlan::writeElement(XMLOutput *o, const Keyword& tag, mode m) const 00134 { 00135 o->BeginObject(tag); 00136 o->writeElement(Tags::tag_date, getDate()); 00137 o->writeElement(Tags::tag_quantity, getQuantity()); 00138 o->writeElement(Tags::tag_onhand, getOnhand()); 00139 o->writeElement(Tags::tag_minimum, getMin()); 00140 o->writeElement(Tags::tag_maximum, getMax()); 00141 if (!dynamic_cast<OperationPlan*>(o->getCurrentObject())) 00142 o->writeElement(Tags::tag_operationplan, &*getOperationPlan()); 00143 00144 // Write pegging info 00145 if (o->getContentType() == XMLOutput::PLANDETAIL) 00146 { 00147 // Write the upstream pegging 00148 PeggingIterator k(this, false); 00149 if (k) --k; 00150 for (; k; --k) 00151 { 00152 o->BeginObject(Tags::tag_pegging, Tags::tag_level, k.getLevel()); 00153 o->writeElement(Tags::tag_quantity, k.getQuantityDemand()); 00154 o->writeElement(Tags::tag_factor, k.getFactor()); 00155 if (!k.getPegged()) o->writeElement(Tags::tag_id, "unpegged"); 00156 o->writeElement(Tags::tag_buffer, Tags::tag_name, k.getBuffer()->getName()); 00157 if (k.getConsumingOperationplan()) 00158 o->writeElement(Tags::tag_consuming, 00159 Tags::tag_id, k.getConsumingOperationplan()->getIdentifier(), 00160 Tags::tag_operation, k.getConsumingOperationplan()->getOperation()->getName()); 00161 if (k.getProducingOperationplan()) 00162 o->writeElement(Tags::tag_producing, 00163 Tags::tag_id, k.getProducingOperationplan()->getIdentifier(), 00164 Tags::tag_operation, k.getProducingOperationplan()->getOperation()->getName()); 00165 o->writeElement(Tags::tag_dates, DateRange(k.getProducingDate(),k.getConsumingDate())); 00166 o->EndObject(Tags::tag_pegging); 00167 } 00168 00169 // Write the downstream pegging 00170 PeggingIterator l(this, true); 00171 if (l) ++l; 00172 for (; l; ++l) 00173 { 00174 o->BeginObject(Tags::tag_pegging, Tags::tag_level, l.getLevel()); 00175 o->writeElement(Tags::tag_quantity, l.getQuantityDemand()); 00176 o->writeElement(Tags::tag_factor, l.getFactor()); 00177 if (!l.getPegged()) o->writeElement(Tags::tag_id, "unpegged"); 00178 o->writeElement(Tags::tag_buffer, Tags::tag_name, l.getBuffer()->getName()); 00179 if (l.getConsumingOperationplan()) 00180 o->writeElement(Tags::tag_consuming, 00181 Tags::tag_id, l.getConsumingOperationplan()->getIdentifier(), 00182 Tags::tag_operation, l.getConsumingOperationplan()->getOperation()->getName()); 00183 if (l.getProducingOperationplan()) 00184 o->writeElement(Tags::tag_producing, 00185 Tags::tag_id, l.getProducingOperationplan()->getIdentifier(), 00186 Tags::tag_operation, l.getProducingOperationplan()->getOperation()->getName()); 00187 o->writeElement(Tags::tag_dates, DateRange(l.getProducingDate(),l.getConsumingDate())); 00188 o->EndObject(Tags::tag_pegging); 00189 } 00190 } 00191 00192 o->EndObject(tag); 00193 } 00194 00195 00196 PyObject* FlowPlan::getattro(const Attribute& attr) 00197 { 00198 if (attr.isA(Tags::tag_operationplan)) 00199 return PythonObject(getOperationPlan()); 00200 if (attr.isA(Tags::tag_quantity)) 00201 return PythonObject(getQuantity()); 00202 if (attr.isA(Tags::tag_flow)) 00203 return PythonObject(getFlow()); 00204 if (attr.isA(Tags::tag_date)) 00205 return PythonObject(getDate()); 00206 if (attr.isA(Tags::tag_onhand)) 00207 return PythonObject(getOnhand()); 00208 if (attr.isA(Tags::tag_buffer)) // Convenient shortcut 00209 return PythonObject(getFlow()->getBuffer()); 00210 if (attr.isA(Tags::tag_operation)) // Convenient shortcut 00211 return PythonObject(getFlow()->getOperation()); 00212 return NULL; 00213 } 00214 00215 00216 int FlowPlanIterator::initialize() 00217 { 00218 // Initialize the type 00219 PythonType& x = PythonExtension<FlowPlanIterator>::getType(); 00220 x.setName("flowplanIterator"); 00221 x.setDoc("frePPLe iterator for flowplan"); 00222 x.supportiter(); 00223 return x.typeReady(); 00224 } 00225 00226 00227 PyObject* FlowPlanIterator::iternext() 00228 { 00229 FlowPlan* fl; 00230 if (buffer_or_opplan) 00231 { 00232 // Skip uninteresting entries 00233 while (*bufiter != buf->getFlowPlans().end() && (*bufiter)->getQuantity()==0.0) 00234 ++(*bufiter); 00235 if (*bufiter == buf->getFlowPlans().end()) return NULL; 00236 fl = const_cast<FlowPlan*>(static_cast<const FlowPlan*>(&*((*bufiter)++))); 00237 } 00238 else 00239 { 00240 // Skip uninteresting entries 00241 while (*opplaniter != opplan->endFlowPlans() && (*opplaniter)->getQuantity()==0.0) 00242 ++(*opplaniter); 00243 if (*opplaniter == opplan->endFlowPlans()) return NULL; 00244 fl = static_cast<FlowPlan*>(&*((*opplaniter)++)); 00245 } 00246 Py_INCREF(fl); 00247 return const_cast<FlowPlan*>(fl); 00248 } 00249 00250 } // end namespace