PyObject* FlowPlan::getattro(const Attribute& attr) { if (attr.isA(Tags::tag_operationplan)) return PythonObject(getOperationPlan()); if (attr.isA(Tags::tag_quantity)) return PythonObject(getQuantity()); if (attr.isA(Tags::tag_flow)) return PythonObject(getFlow()); if (attr.isA(Tags::tag_date)) return PythonObject(getDate()); if (attr.isA(Tags::tag_onhand)) return PythonObject(getOnhand()); if (attr.isA(Tags::tag_buffer)) // Convenient shortcut return PythonObject(getFlow()->getBuffer()); if (attr.isA(Tags::tag_operation)) // Convenient shortcut return PythonObject(getFlow()->getOperation()); return NULL; }
// Remember that this method only superficially looks like a normal // writeElement() method. DECLARE_EXPORT void FlowPlan::writeElement(XMLOutput *o, const Keyword& tag, mode m) const { o->BeginObject(tag); o->writeElement(Tags::tag_date, getDate()); o->writeElement(Tags::tag_quantity, getQuantity()); o->writeElement(Tags::tag_onhand, getOnhand()); o->writeElement(Tags::tag_minimum, getMin()); o->writeElement(Tags::tag_maximum, getMax()); if (!dynamic_cast<OperationPlan*>(o->getCurrentObject())) o->writeElement(Tags::tag_operationplan, &*getOperationPlan()); // Write pegging info. if (o->getContentType() == XMLOutput::PLANDETAIL) { // Write the upstream pegging PeggingIterator k(this, false); if (k) --k; for (; k; --k) o->writeElement(Tags::tag_pegging, Tags::tag_level, -k.getLevel(), Tags::tag_operationplan, k.getOperationPlan()->getIdentifier(), Tags::tag_quantity, k.getQuantity() ); // Write the downstream pegging PeggingIterator l(this, true); if (l) ++l; for (; l; ++l) o->writeElement(Tags::tag_pegging, Tags::tag_level, l.getLevel(), Tags::tag_operationplan, l.getOperationPlan()->getIdentifier(), Tags::tag_quantity, l.getQuantity() ); } o->EndObject(tag); }
bool OperationPlan::updateFeasible() { if (!getOperation()->getDetectProblems()) { // No problems to be flagged on this operation setFeasible(true); return true; } // The implementation of this method isn't really cleanly object oriented. It uses // logic which only the different resource and buffer implementation classes should be // aware. if (firstsubopplan) { // Check feasibility of child operationplans for (OperationPlan *i = firstsubopplan; i; i = i->nextsubopplan) { if (!i->updateFeasible()) { setFeasible(false); return false; } } } else { // Before current and before fence problems are only detected on child operationplans if (getConfirmed()) { if (dates.getEnd() < Plan::instance().getCurrent()) { // Before current violation setFeasible(false); return false; } } else { if (dates.getStart() < Plan::instance().getCurrent()) { // Before current violation setFeasible(false); return false; } else if (dates.getStart() < Plan::instance().getCurrent() + oper->getFence() && getProposed()) { // Before fence violation setFeasible(false); return false; } } } if (nextsubopplan && getEnd() > nextsubopplan->getStart() + Duration(1L) && !nextsubopplan->getConfirmed() && owner && !owner->getOperation()->hasType<OperationSplit>() ) { // Precedence violation // Note: 1 second grace period for precedence problems to avoid rounding issues setFeasible(false); return false; } // Verify the capacity constraints for (auto ldplan = getLoadPlans(); ldplan != endLoadPlans(); ++ldplan) { if (ldplan->getResource()->hasType<ResourceDefault>() && ldplan->getQuantity() > 0) { auto curMax = ldplan->getMax(); for ( auto cur = ldplan->getResource()->getLoadPlans().begin(&*ldplan); cur != ldplan->getResource()->getLoadPlans().end(); ++cur ) { if (cur->getOperationPlan() == this && cur->getQuantity() < 0) break; if (cur->getEventType() == 4) curMax = cur->getMax(false); if ( cur->getEventType() != 5 && cur->isLastOnDate() && cur->getOnhand() > curMax + ROUNDING_ERROR ) { // Overload on default resource setFeasible(false); return false; } } } else if (ldplan->getResource()->hasType<ResourceBuckets>()) { for ( auto cur = ldplan->getResource()->getLoadPlans().begin(&*ldplan); cur != ldplan->getResource()->getLoadPlans().end() && cur->getEventType() != 2; ++cur ) { if (cur->getOnhand() < -ROUNDING_ERROR) { // Overloaded capacity on bucketized resource setFeasible(false); return false; } } } } // Verify the material constraints for (auto flplan = beginFlowPlans(); flplan != endFlowPlans(); ++flplan) { if ( !flplan->getFlow()->isConsumer() || flplan->getBuffer()->hasType<BufferInfinite>() ) continue; auto flplaniter = flplan->getBuffer()->getFlowPlans(); for (auto cur = flplaniter.begin(&*flplan); cur != flplaniter.end(); ++cur) { if (cur->getOnhand() < -ROUNDING_ERROR && cur->isLastOnDate()) { // Material shortage setFeasible(false); return false; } } } // After all checks, it turns out to be feasible setFeasible(true); return true; }