problems_demand.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * *
3  * Copyright (C) 2007-2012 by Johan De Taeye, frePPLe bvba *
4  * *
5  * This library is free software; you can redistribute it and/or modify it *
6  * under the terms of the GNU Affero General Public License as published *
7  * by the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This library is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU Affero General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU Affero General Public *
16  * License along with this program. *
17  * If not, see <http://www.gnu.org/licenses/>. *
18  * *
19  ***************************************************************************/
20 
21 #define FREPPLE_CORE
22 #include "frepple/model.h"
23 
24 namespace frepple
25 {
26 
27 
29 {
30  // The relation between the demand and the related problem classes is such
31  // that the demand object is the only active one. The problem objects are
32  // fully controlled and managed by the associated demand object.
33 
34  // A flag for each problem type that may need to be created
35  bool needsNotPlanned(false);
36  bool needsEarly(false);
37  bool needsLate(false);
38  bool needsShort(false);
39  bool needsExcess(false);
40 
41  // Problem detection disabled on this demand
42  if (!getDetectProblems()) return;
43 
44  // Check which problems need to be created
45  if (deli.empty())
46  {
47  // Check if a new ProblemDemandNotPlanned needs to be created
48  if (getQuantity()>0.0) needsNotPlanned = true;
49  }
50  else
51  {
52  // Loop through the deliveries
53  for (OperationPlan_list::iterator i = deli.begin(); i!=deli.end(); ++i)
54  {
55  // Check for ProblemLate problem
56  long d(getDue() - (*i)->getDates().getEnd());
57  if (d < 0L) needsLate = true;
58  // Check for ProblemEarly problem
59  else if (d > 0L) needsEarly = true;
60  }
61 
62  // Check for ProblemShort problem
63  double plannedqty = getPlannedQuantity();
64  if (plannedqty + ROUNDING_ERROR < qty) needsShort = true;
65 
66  // Check for ProblemExcess Problem
67  if (plannedqty - ROUNDING_ERROR > qty) needsExcess = true;
68  }
69 
70  // Loop through the existing problems
71  for (Problem::const_iterator j = Problem::begin(this, false);
72  j!=Problem::end(); )
73  {
74  // Need to increment now and define a pointer to the problem, since the
75  // problem can be deleted soon (which invalidates the iterator).
76  Problem& curprob = *j;
77  ++j;
78  // The if-statement keeps the problem detection code concise and
79  // concentrated. However, a drawback of this design is that a new Problem
80  // subclass will also require a new Demand subclass. I think such a link
81  // is acceptable.
82  if (typeid(curprob) == typeid(ProblemEarly))
83  {
84  // if: problem needed and it exists already
85  if (needsEarly) needsEarly = false;
86  // else: problem not needed but it exists already
87  else delete &curprob;
88  }
89  else if (typeid(curprob) == typeid(ProblemDemandNotPlanned))
90  {
91  if (needsNotPlanned) needsNotPlanned = false;
92  else delete &curprob;
93  }
94  else if (typeid(curprob) == typeid(ProblemLate))
95  {
96  if (needsLate) needsLate = false;
97  else delete &curprob;
98  }
99  else if (typeid(curprob) == typeid(ProblemShort))
100  {
101  if (needsShort) needsShort = false;
102  else delete &curprob;
103  }
104  else if (typeid(curprob) == typeid(ProblemExcess))
105  {
106  if (needsExcess) needsExcess = false;
107  else delete &curprob;
108  }
109  // Note that there may be other demand exceptions that are not caught in
110  // this loop. These are problems defined and managed by subclasses.
111  }
112 
113  // Create the problems that are required but aren't existing yet.
114  if (needsNotPlanned) new ProblemDemandNotPlanned(this);
115  if (needsLate) new ProblemLate(this);
116  if (needsEarly) new ProblemEarly(this);
117  if (needsShort) new ProblemShort(this);
118  if (needsExcess) new ProblemExcess(this);
119 }
120 
121 
123 {
124  assert(getDemand() && !getDemand()->getDelivery().empty());
125  TimePeriod t(getDemand()->getLatestDelivery()->getDates().getEnd()
126  - getDemand()->getDue());
127  return string("Demand '") + getDemand()->getName() + "' planned "
128  + string(t) + " after its due date";
129 }
130 
131 
133 {
134  assert(getDemand() && !getDemand()->getDelivery().empty());
135  TimePeriod t(getDemand()->getDue()
136  - getDemand()->getEarliestDelivery()->getDates().getEnd());
137  return string("Demand '") + getDemand()->getName() + "' planned "
138  + string(t) + " before its due date";
139 }
140 
141 }