00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "forecast.h"
00028
00029 namespace module_forecast
00030 {
00031
00032 int PythonForecast::initialize(PyObject* m)
00033 {
00034
00035 getType().addMethod("timeseries", timeseries, METH_VARARGS,
00036 "Set the future based on the timeseries of historical data");
00037
00038
00039 return FreppleClass<PythonForecast,PythonDemand,Forecast>::initialize(m);
00040 }
00041
00042
00043 PyObject* PythonForecast::getattro(const Attribute& attr)
00044 {
00045 if (!obj) return Py_BuildValue("");
00046 if (attr.isA(Tags::tag_calendar))
00047 return PythonObject(obj->getCalendar());
00048 else if (attr.isA(Tags::tag_discrete))
00049 return PythonObject(obj->getDiscrete());
00050 return PythonDemand(obj).getattro(attr);
00051 }
00052
00053
00054 int PythonForecast::setattro(const Attribute& attr, const PythonObject& field)
00055 {
00056 if (attr.isA(Tags::tag_calendar))
00057 {
00058 if (!field.check(PythonCalendar::getType()))
00059 {
00060 PyErr_SetString(PythonDataException, "forecast calendar must be of type calendar");
00061 return -1;
00062 }
00063 Calendar* y = static_cast<PythonCalendar*>(static_cast<PyObject*>(field))->obj;
00064 obj->setCalendar(y);
00065 }
00066 else if (attr.isA(Tags::tag_discrete))
00067 obj->setDiscrete(field.getBool());
00068 else
00069 return PythonDemand(obj).setattro(attr, field);
00070 return 0;
00071 }
00072
00073
00074 extern "C" PyObject* PythonForecast::timeseries(PyObject *self, PyObject *args)
00075 {
00076
00077 Forecast* forecast = static_cast<PythonForecast*>(self)->obj;
00078
00079
00080 PyObject* history;
00081 PyObject* buckets = NULL;
00082 int ok = PyArg_ParseTuple(args, "O|O", &history, &buckets);
00083 if (!ok) return NULL;
00084
00085
00086 PyObject *historyiterator = PyObject_GetIter(history);
00087 PyObject *bucketiterator = NULL;
00088 if (!historyiterator)
00089 {
00090 PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00091 return NULL;
00092 }
00093 if (buckets) bucketiterator = PyObject_GetIter(buckets);
00094 if (!bucketiterator)
00095 {
00096 PyErr_Format(PyExc_AttributeError,"Invalid type for time series");
00097 return NULL;
00098 }
00099
00100
00101 double data[300];
00102 unsigned int historycount = 0;
00103 PyObject *item;
00104 while (item = PyIter_Next(historyiterator))
00105 {
00106 data[historycount++] = PyFloat_AsDouble(item);
00107 Py_DECREF(item);
00108 if (historycount>=300) break;
00109 }
00110 Py_DECREF(historyiterator);
00111
00112
00113 Date bucketdata[300];
00114 unsigned int bucketcount = 0;
00115 while (item = PyIter_Next(bucketiterator))
00116 {
00117 bucketdata[bucketcount++] = PythonObject(item).getDate();
00118 Py_DECREF(item);
00119 if (bucketcount>=300) break;
00120 }
00121 Py_DECREF(bucketiterator);
00122
00123 Py_BEGIN_ALLOW_THREADS
00124 try {
00125
00126 forecast->generateFutureValues
00127 (data, historycount, bucketdata, bucketcount, true);
00128 }
00129 catch (...)
00130 {
00131 Py_BLOCK_THREADS;
00132 PythonType::evalException();
00133 return NULL;
00134 }
00135 Py_END_ALLOW_THREADS
00136 return Py_BuildValue("");
00137 }
00138
00139
00140 int PythonForecastBucket::initialize(PyObject* m)
00141 {
00142
00143
00144 PythonType& x = getType();
00145 x.setName("demand_forecastbucket");
00146 x.setDoc("frePPLe forecastbucket");
00147 x.supportgetattro();
00148 x.supportsetattro();
00149 const_cast<MetaCategory*>(Demand::metadata)->factoryPythonProxy = proxy;
00150 return x.typeReady(m);
00151 }
00152
00153
00154 PyObject* PythonForecastBucket::getattro(const Attribute& attr)
00155 {
00156 if (!obj) return Py_BuildValue("");
00157 if (attr.isA(Tags::tag_startdate))
00158 return PythonObject(obj->getDueRange().getStart());
00159 if (attr.isA(Tags::tag_enddate))
00160 return PythonObject(obj->getDueRange().getEnd());
00161 if (attr.isA(Forecast::tag_total))
00162 return PythonObject(obj->getTotal());
00163 if (attr.isA(Forecast::tag_consumed))
00164 return PythonObject(obj->getConsumed());
00165 if (attr.isA(Tags::tag_weight))
00166 return PythonObject(obj->getWeight());
00167 return PythonDemand(obj).getattro(attr);
00168 }
00169
00170
00171 int PythonForecastBucket::setattro(const Attribute& attr, const PythonObject& field)
00172 {
00173 if (attr.isA(Forecast::tag_total))
00174 obj->setTotal(field.getDouble());
00175 else if (attr.isA(Forecast::tag_consumed))
00176 obj->setConsumed(field.getDouble());
00177 else if (attr.isA(Tags::tag_weight))
00178 obj->setWeight(field.getDouble());
00179 else
00180 return PythonDemand(obj).setattro(attr, field);
00181 return 0;
00182 }
00183
00184
00185 PyObject* PythonForecastSolver::getattro(const Attribute& attr)
00186 {
00187 if (!obj) return Py_BuildValue("");
00188 return PythonSolver(obj).getattro(attr);
00189 }
00190
00191
00192 int PythonForecastSolver::setattro(const Attribute& attr, const PythonObject& field)
00193 {
00194 return PythonSolver(obj).setattro(attr, field);
00195 }
00196
00197
00198 }