Index: /trunk/FACT++/src/scheduler.cc
===================================================================
--- /trunk/FACT++/src/scheduler.cc	(revision 10617)
+++ /trunk/FACT++/src/scheduler.cc	(revision 10618)
@@ -23,16 +23,19 @@
 #include <vector>
 
-namespace ba    = boost::asio;
-namespace bs    = boost::system;
-
-using ba::deadline_timer;
-using ba::ip::tcp;
-
-using namespace std;
-
-
 #include "LocalControl.h"
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <mysql++/mysql++.h>
+
+
+namespace ba    = boost::asio;
+namespace bs    = boost::system;
+
+using ba::deadline_timer;
+using ba::ip::tcp;
+
+using namespace std;
+using namespace boost::gregorian;
+using namespace boost::posix_time;
+
 
 // string containing database information
@@ -52,5 +55,5 @@
 // other things to do
 //
-// define what is error and warning
+// define what to transmit as info/warn/error
 
 
@@ -62,5 +65,4 @@
 
 // missing:
-// from / to for the time range for which the scheduling shall be done
 //
 // calculate time for std obs
@@ -71,4 +73,10 @@
 // return errors
 // get input from sendcommand
+
+// in which cases should the scheduler go in error state?
+//   when db is unavailable
+// does one also need a 'set scheduler to ready' function then?
+// do we want any error state at all?
+
 
 // =========================================================================
@@ -170,8 +178,14 @@
     int Schedule()
     {
+        bool error = false;
+
         boost::posix_time::time_duration runtimec(0, 3, 0);
         boost::posix_time::time_duration runtimep(0, 3, 0);
         boost::posix_time::time_duration mintime(1, 0, 0);
         boost::posix_time::time_duration repostime(0, 5, 0);
+        //boost::posix_time::ptime startsched=microsec_clock::local_time();
+        boost::posix_time::ptime startsched(microsec_clock::local_time());
+        boost::posix_time::ptime stopsched=startsched+years(1);
+        cout << "Scheduling for the period from " << startsched << " to " << stopsched << endl;
 
         stringstream str;
@@ -246,26 +260,11 @@
         int counter2=0;
         int counter3=0;
+        cout << "Obs: <obskey> <sourcename>(<sourcekey>, <fluxweight>) from <starttime> to <stoptime>" << endl;
         for (vector<mysqlpp::Row>::iterator v=res.begin(); v<res.end(); v++)
         {
-            cout << "Obskey: " << (*v)[0].c_str() << " source: " << (*v)[4].c_str() << "(" << (*v)[5].c_str() << ")" << flush;
-            cout << " T1 " << (*v)[1].c_str() << " T2: " << (*v)[2].c_str() << " (c " << counter << " " << counter2 << ")" << endl;
-
-            /*
-            cout << " 0 " << (*v)[0].c_str() << endl;
-            cout << " 1 " << (*v)[1].c_str() << endl;
-            cout << " 2 " << (*v)[2].c_str() << endl;
-            cout << " 3 " << (*v)[3].c_str() << endl;
-            cout << " 4 " << (*v)[4].c_str() << endl;
-            cout << " 5 " << (*v)[5].c_str() << endl;
-            cout << " 6 " << (*v)[6].c_str() << endl;
-            cout << " 7 " << (*v)[7].c_str() << endl;
-            cout << " 8 " << (*v)[8].c_str() << endl;
-            cout << " 9 " << (*v)[9].c_str() << endl;
-            cout << " 10 " << (*v)[10].c_str() << endl;
-            cout << " 11 " << (*v)[11].c_str() << endl;
-            cout << " 12 " << (*v)[12].c_str() << endl;
-            cout << " 13 " << (*v)[13].c_str() << endl;
-            cout << " 14 " << (*v)[14].c_str() << endl;
-            */
+            cout << "  Obs: " << (*v)[0].c_str() << " " << (*v)[4].c_str() << "(" << (*v)[5].c_str() << flush;
+            cout << ", " << (*v)[7].c_str() << ")" << flush;
+            cout << " from " << (*v)[1].c_str() << " to " << (*v)[2].c_str() << endl;
+
             //0: obskey
             //1: startime
@@ -300,52 +299,24 @@
             if (!(*v)[0].is_null())
                 olist[counter].obskey=(*v)[0];
-            //else
-            //    cout << "no obskey" << endl;
             if (!(*v)[12].is_null())
                 olist[counter].obsmode=(*v)[12];
-            //else
-            //    cout << "no obsmode" << endl;
             if (!(*v)[13].is_null())
                 olist[counter].obstype=(*v)[13];
-            //else
-            //    cout << "no obstype" << endl;
             if (!(*v)[14].is_null())
                 olist[counter].telsetup=(*v)[14];
-            //else
-            //    cout << "no telsetup" << endl;
             if (!(*v)[6].is_null())
                 olist[counter].splitflag=(*v)[6];
-            //else
-            //{
-            //    cout << "no splitflag" << endl;
-                ////stringstream str;
-                ////str << "no splitflag";
-                //T::Message("no splitflag");
-                //T::Error("---> no splitflag");
-                //T::Warn("+++ no splitflag");
-            //}
             if (!(*v)[7].is_null())
                 olist[counter].fluxweight=(*v)[7];
             else
-            {
-                olist[counter].fluxweight=0;
-            //    cout << "no fluxweight" << endl;
-            }
+                olist[counter].fluxweight=0;//set fluxweight to 0 for check below
             if (!(*v)[8].is_null())
                 olist[counter].slope=(*v)[8];
-            //else
-            //    cout << "no slope" << endl;
             if (!(*v)[9].is_null())
                 olist[counter].flux=(*v)[9];
-            //else
-            //    cout << "no flux" << endl;
             if (!(*v)[10].is_null())
                 olist[counter].ra=(*v)[10];
-            //else
-            //    cout << "no ra" << endl;
             if (!(*v)[11].is_null())
                 olist[counter].dec=(*v)[11];
-            //else
-            //    cout << "no dec" << endl;
 
             // time_duration cannot be used, as only up to 99 hours are handeled
@@ -428,12 +399,24 @@
             counter++;
         }
+        stringstream fixedobsmsg;
+        fixedobsmsg << obsfixedlist.size() << " fixed observations found. ";
+        T::Message(fixedobsmsg);
         cout << obsfixedlist.size() << " fixed observations found. " << endl;
+
+        stringstream stdobsmsg;
+        stdobsmsg << obsstdlist.size() << " standard observations found. ";
+        T::Message(stdobsmsg);
         cout << obsstdlist.size() << " standard observations found. " << endl;
 
         // loop to add the fixed observations to the ScheduledObs list
-        // missing: checks and evaluation
-        //  * check for sun
-        //  * check for moon
+        // performed checks:
+        //   * overlap of fixed observations: the overlap is split half-half
+        //   * check for scheduling time range: only take into account fixed obs within the range
+        // missing checks and evaluation
+        //   * check for mintime (pb with overlap checks)
+        //   * check for sun
+        //   * check for moon
         counter2=0;
+        int skipcounter=0;
         boost::posix_time::ptime finalobsfixedstart;
         boost::posix_time::ptime finalobsfixedstop;
@@ -446,4 +429,14 @@
         for (vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
         {
+            if (obsfixedlist[counter2].obsfixedstart < startsched
+                || obsfixedlist[counter2].obsfixedstop > stopsched)
+            {
+                stringstream skipfixedobsmsg;
+                skipfixedobsmsg  << "Skip 1 fixed observation (obskey " << obsfixedlist[counter2].obskey_fixed << ") as it is out of scheduling time range.";
+                T::Message(skipfixedobsmsg);
+                counter2++;
+                skipcounter++;
+                continue;
+            }
             counter3=0;
             delta1=delta0;
@@ -451,16 +444,7 @@
             finalobsfixedstart=obsfixedlist[counter2].obsfixedstart;
             finalobsfixedstop=obsfixedlist[counter2].obsfixedstop;
-            //cout << "final: " << finalobsfixedstart << " - " << finalobsfixedstop << endl;
 
             for (vobs5=obsfixedlist.begin(); vobs5!=obsfixedlist.end(); vobs5++)
             {
-                //cout << "startc" << obsfixedlist[counter2].obsfixedstart << "  --  " << flush;
-                //cout << "stopc" << obsfixedlist[counter2].obsfixedstop << "  --  " << flush;
-                //cout << "start" << (*vobs5).obsfixedstart << "  --  " << flush;
-                //cout << "stop" << (*vobs5).obsfixedstop << "  --  " << flush;
-
-                //if (obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstop
-                //    && (*vobs5).obsfixedstop < obsfixedlist[counter2].obsfixedstop
-                //    && counter2!=counter3)
                 if ((*vobs5).obsfixedstart < obsfixedlist[counter2].obsfixedstop
                     && obsfixedlist[counter2].obsfixedstop <= (*vobs5).obsfixedstop
@@ -468,15 +452,10 @@
                     && counter2!=counter3)
                 {
-                    //delta1=((*vobs5).obsfixedstop-obsfixedlist[counter2].obsfixedstart)/2;
                     delta1=(obsfixedlist[counter2].obsfixedstop-(*vobs5).obsfixedstart)/2;
                     finalobsfixedstop=obsfixedlist[counter2].obsfixedstop-delta1;
-                    //cout << "delta1 " << delta1 << endl;
                     stringstream warndelta1;
                     warndelta1 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The stoptime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
                     T::Warn(warndelta1);
                 }
-                //if (obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstart
-                //    && (*vobs5).obsfixedstart < obsfixedlist[counter2].obsfixedstop
-                //    && counter2!=counter3)
                 if ((*vobs5).obsfixedstart <= obsfixedlist[counter2].obsfixedstart
                     && obsfixedlist[counter2].obsfixedstart < (*vobs5).obsfixedstop
@@ -486,5 +465,4 @@
                     delta2=((*vobs5).obsfixedstop-obsfixedlist[counter2].obsfixedstart)/2;
                     finalobsfixedstart=obsfixedlist[counter2].obsfixedstart+delta2;
-                    //cout << "delta2 " << delta2 << endl;
                     stringstream warndelta2;
                     warndelta2 << "Overlap between two fixed observations (" << obsfixedlist[counter2].obskey_fixed << " " << (*vobs5).obskey_fixed << "). The starttime of " << obsfixedlist[counter2].obskey_fixed << " has been changed.";
@@ -492,22 +470,44 @@
                 }
                 counter3++;
-                //cout << endl;
             }
 
-            //cout << "-> final: " << finalobsfixedstart << " - " << finalobsfixedstop << endl;
-            obslist.resize(counter2+1);
-            //obslist[counter2].obsstart=obsfixedlist[counter2].obsfixedstart;
-            obslist[counter2].obsstart=finalobsfixedstart;
-            //obslist[counter2].obsstop=obsfixedlist[counter2].obsfixedstop;
-            obslist[counter2].obsstop=finalobsfixedstop;
-            obslist[counter2].sourcename_obs=obsfixedlist[counter2].sourcename_fixed;
-            obslist[counter2].obsmode_obs=obsfixedlist[counter2].obsmode_fixed;
-            obslist[counter2].obstype_obs=obsfixedlist[counter2].obstype_fixed;
-            obslist[counter2].telsetup_obs=obsfixedlist[counter2].telsetup_fixed;
-            obslist[counter2].sourcekey_obs=obsfixedlist[counter2].sourcekey_fixed;
+            int num=counter2-skipcounter;
+            obslist.resize(num+1);
+            obslist[num].obsstart=finalobsfixedstart;
+            obslist[num].obsstop=finalobsfixedstop;
+            obslist[num].sourcename_obs=obsfixedlist[counter2].sourcename_fixed;
+            obslist[num].obsmode_obs=obsfixedlist[counter2].obsmode_fixed;
+            obslist[num].obstype_obs=obsfixedlist[counter2].obstype_fixed;
+            obslist[num].telsetup_obs=obsfixedlist[counter2].telsetup_fixed;
+            obslist[num].sourcekey_obs=obsfixedlist[counter2].sourcekey_fixed;
             counter2++;
-            //cout << "  " << (*vobs).sourcename_fixed <<  " " << (*vobs).obsfixedstart << flush;
-            //cout << " - " << (*vobs).obsfixedstop << endl;
-        }
+            cout << "  " << (*vobs).sourcename_fixed <<  " " << (*vobs).obsfixedstart << flush;
+            cout << " - " << (*vobs).obsfixedstop << endl;
+        }
+        stringstream obsmsg;
+        obsmsg << "Added " << obslist.size() << " fixed observations to ScheduledObs. ";
+        T::Message(obsmsg);
+        cout << "Added " << obslist.size() << " fixed observations to ScheduledObs. " << endl;
+
+        for (int i=0; i<(int)obsstdlist.size(); i++)
+        {
+            for (int j=0; j<(int)obsstdlist.size(); j++)
+            {
+                if (obsstdlist[i].sourcekey_std == obsstdlist[j].sourcekey_std && i!=j)
+                {
+                    cout << "One double sourcekey in std observations: " << obsstdlist[j].sourcekey_std << endl;
+                    stringstream errdoublestd;
+                    errdoublestd << "One double sourcekey in std observations: " << obsstdlist[j].sourcekey_std << " (" << obsstdlist[j].sourcename_std << ").";
+                    T::Error(errdoublestd);
+                    T::Message("Scheduling stopped.");
+                    return error ? T::kSM_Error : T::kSM_Ready;
+                }
+            }
+        }
+
+        // loop over nights
+        //   calculate sunset and sunrise
+        //   check if there is already scheduled obs in that night
+        //
 
         // in this loop the standard observations shall be
@@ -522,11 +522,11 @@
         }
 
-        // in this loop from the scheduled observations the list
-        // of scheduled runs shall be calculated
+        // in this loop the ScheduledRuns are filled
+        //  (only data runs -> no runtype yet)
+        // might be merged with next loop
         counter2=0;
         struct vector<ScheduledObs>::iterator vobs3;
         for (vobs3=obslist.begin(); vobs3!=obslist.end(); vobs3++)
         {
-            // add runtype and runtime calculations
             runlist.resize(counter2+1);
             runlist[counter2].runstart=obslist[counter2].obsstart;
@@ -538,5 +538,5 @@
             runlist[counter2].sourcekey_run=obslist[counter2].sourcekey_obs;
             counter2++;
-            cout << (*vobs3).sourcename_obs << endl;
+            //cout << (*vobs3).sourcename_obs << endl;
         }
 
@@ -551,5 +551,9 @@
         }
 
+        // in this loop the ScheduledRuns are inserted to the DB
+        //   before the runtimes are adapted according to
+        //   duration of P-Run, C-Run and repositioning
         counter3=0;
+        int insertcount=0;
         boost::posix_time::ptime finalstarttime;
         boost::posix_time::ptime finalstoptime;
@@ -595,7 +599,11 @@
                     throw;
                 }
+                insertcount++;
             }
             counter3++;
         }
+        stringstream insertmsg;
+        insertmsg << "Inserted " << insertcount << " runs into the DB.";
+        T::Message(insertmsg);
         //usleep(3000000);
         T::Message("Scheduling done.");
@@ -603,5 +611,5 @@
         fSessionId = -1;
 
-        bool error = false;
+        //bool error = false;
         return error ? T::kSM_Error : T::kSM_Ready;
     }
