Index: /trunk/FACT++/src/scheduler.cc
===================================================================
--- /trunk/FACT++/src/scheduler.cc	(revision 10595)
+++ /trunk/FACT++/src/scheduler.cc	(revision 10596)
@@ -2,4 +2,5 @@
 #include <boost/bind.hpp>
 #include <boost/thread.hpp>
+#include <boost/regex.hpp>
 #include <boost/asio/deadline_timer.hpp>
 
@@ -34,4 +35,36 @@
 string database;
 
+// things to be done/checked/changed
+// * do not use --database, but sth like --database-scheduler
+//   to be independent of the configuration database
+// * check if the following include is really needed
+//   #include <boost/date_time/posix_time/posix_time.hpp>
+// * string database not as global variable
+//   pass reference to conf and the string as a member of the class
+//   (see chat of 4.5.2011)
+// * move definition of config parameters to AutoScheduler class
+//   + read in from config
+
+// other things to do
+//
+// define what is error and warning
+
+
+// config parameters
+// mintime
+// runtimec
+// runtimep
+// repostime
+
+// missing:
+// from / to for the time range for which the scheduling shall be done
+//
+// calculate time for std obs
+// calculate sun set/rise
+//
+// check for double std sources
+//
+// return errors
+// get input from sendcommand
 
 // =========================================================================
@@ -51,8 +84,18 @@
     {
         int obskey;
+        int obsmode;
+        int obstype;
+        int splitflag;
+        int telsetup;
+        float fluxweight;
+        float slope;
+        float flux;
+        float ra;
+        float dec;
         boost::posix_time::ptime starttime;
         boost::posix_time::ptime stoptime;
         boost::posix_time::time_duration duration_db;
         string sourcename;
+        int sourcekey;
     };
 
@@ -63,7 +106,16 @@
         string sourcename_fixed;
         int obsmode_fixed;
+        int obstype_fixed;
+        int telsetup_fixed;
+        float ra_fixed;
+        float dec_fixed;
         boost::posix_time::ptime obsfixedstart;
         boost::posix_time::ptime obsfixedstop;
     };
+
+    // will need other types of obs
+    // FloatingObs (duration < stop-start + splitflag no)
+    // FloatingSplittedObs (duration < stop-start + splitflag yes)
+    // FixedSlot, i.e. just block a time slot
 
     struct StdObs
@@ -73,4 +125,11 @@
         string sourcename_std;
         int obsmode_std;
+        int obstype_std;
+        int telsetup_std;
+        float fluxweight_std;
+        float slope_std;
+        float flux_std;
+        float ra_std;
+        float dec_std;
         boost::posix_time::ptime obsstdstart;
         boost::posix_time::ptime obsstdstop;
@@ -82,4 +141,6 @@
         string sourcename_obs;
         int obsmode_obs;
+        int obstype_obs;
+        int telsetup_obs;
         boost::posix_time::ptime obsstart;
         boost::posix_time::ptime obsstop;
@@ -88,8 +149,11 @@
     struct ScheduledRun
     {
-        int runnumber;
+        //int runnumber; // to be seen, if runnumber is needed
         int runtype;
-        int sourcekey;
-        int obsmode;
+        int sourcekey_run;
+        string sourcename_run;//for convenience
+        int obsmode_run;
+        int obstype_run;
+        int telsetup_run;
         boost::posix_time::ptime runstart;
         boost::posix_time::ptime runstop;
@@ -98,11 +162,17 @@
     int fSessionId;
 
+
+
     int Schedule()
     {
+        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);
+
         stringstream str;
         str << "Scheduling started -> Preview (id=" << fSessionId << ")";
         T::Message(str);
 
-        //static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))?");
         static const boost::regex expr("(([[:word:].-]+)(:(.+))?@)?([[:word:].-]+)(:([[:digit:]]+))?(/([[:word:].-]+))");
         // 2: user
@@ -112,5 +182,4 @@
         // 9: db
 
-        //string database="root:Ihtp4aDB@localhost:3306/Scheduling";
         boost::smatch what;
         if (!boost::regex_match(database, what, expr, boost::match_extra))
@@ -148,15 +217,8 @@
             throw;
         }
-        //mysqlpp::Connection conn(db.c_str(), server.c_str(), user.c_str(), passwd.c_str(), port);
-        //mysqlpp::Connection conn("Scheduling", "localhost", "root", "Ihtp4aDB", 3306);
-        if (!conn.connected())
-        {
-            cout << "MySQL connection error: " << conn.error() << endl;
-            throw;
-        }
 
         // get observation parameters from DB
-        mysqlpp::Query query = conn.query("SELECT fObservationKEY, fStartTime, fStopTime, fDuration, fSourceName, fSourceKEY, fSplitFlag, fFluxWeight, fObservationModeKEY, fObservationTypeKEY FROM ObservationParameters LEFT JOIN Source USING(fSourceKEY) ORDER BY fObservationKEY");
-        //maybe order by priority?
+        // maybe order by priority?
+        mysqlpp::Query query = conn.query("SELECT fObservationKEY, fStartTime, fStopTime, fDuration, fSourceName, fSourceKEY, fSplitFlag, fFluxWeight, fSlope, fFlux, fRightAscension, fDeclination, fObservationModeKEY, fObservationTypeKEY , fTelescopeSetupKEY FROM ObservationParameters LEFT JOIN Source USING(fSourceKEY) ORDER BY fStartTime");
 
         mysqlpp::StoreQueryResult res = query.store();
@@ -185,4 +247,36 @@
             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;
+            */
+            //0: obskey
+            //1: startime
+            //2: stoptime
+            //3: duration
+            //4: sourcename
+            //5: sourcekey
+            //6: splitflag
+            //7: fluxweight
+            //8: slope
+            //9: flux
+            //10: ra
+            //11: dec
+            //12: obsmode
+            //13: obstype
+            //14: telsetup
             stringstream t1;
             stringstream t2;
@@ -193,5 +287,4 @@
 
             //boost::posix_time::time_duration mintime(0,conf.Get<int>("mintime"), 0);
-            boost::posix_time::time_duration mintime(1, 0, 0);
             t1 >> Time::sql >> olist[counter].starttime;
             t2 >> Time::sql >> olist[counter].stoptime;
@@ -199,5 +292,56 @@
             boost::posix_time::time_period period(olist[counter].starttime, olist[counter].stoptime);
             olist[counter].sourcename=(*v)[4].c_str();
-            olist[counter].obskey=(*v)[0];
+            olist[counter].sourcekey=(*v)[5];
+
+            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;
+            }
+            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
@@ -224,6 +368,22 @@
             */
 
-            // if start and stop time are available, it is a fixed observation
-            if (!(olist[counter].stoptime.is_not_a_date_time() && olist[counter].starttime.is_not_a_date_time()))
+            // always filled: obstype
+            //
+            // fixed observations:
+            //   filled: starttime, stoptime
+            //   not filled: fluxweight
+            //   maybe filled: obsmode, telsetup, source (not filled for FixedSlotObs)
+            //   maybe filled: duration (filled for FloatingObs and FloatingSplittedObs)
+            //   maybe filled: splitflag (filled for FloatingSplittedObs)
+            //
+            // std observations:
+            //   filled: fluxweight, telsetup, obsmore, source
+            //   not filled: starttime, stoptime, duration
+
+            // fixed observations
+            if (!(olist[counter].stoptime.is_not_a_date_time()
+                  && olist[counter].starttime.is_not_a_date_time())
+                && olist[counter].fluxweight==0
+               )
             {
                 obsfixedlist.resize(counter2+1);
@@ -232,11 +392,31 @@
                 obsfixedlist[counter2].sourcename_fixed=olist[counter].sourcename;
                 obsfixedlist[counter2].obskey_fixed=olist[counter].obskey;
+                obsfixedlist[counter2].obstype_fixed=olist[counter].obstype;
+                obsfixedlist[counter2].obsmode_fixed=olist[counter].obsmode;
+                obsfixedlist[counter2].telsetup_fixed=olist[counter].telsetup;
+                obsfixedlist[counter2].sourcekey_fixed=olist[counter].sourcekey;
+                obsfixedlist[counter2].ra_fixed=olist[counter].ra;
+                obsfixedlist[counter2].dec_fixed=olist[counter].dec;
                 counter2++;
             }
-            else
+
+            // std obs
+            if (olist[counter].stoptime.is_not_a_date_time()
+                  && olist[counter].starttime.is_not_a_date_time()
+                && olist[counter].fluxweight>0
+               )
             {
                 obsstdlist.resize(counter3+1);
                 obsstdlist[counter3].sourcename_std=olist[counter].sourcename;
                 obsstdlist[counter3].obskey_std=olist[counter].obskey;
+                obsstdlist[counter3].obsmode_std=olist[counter].obsmode;
+                obsstdlist[counter3].obstype_std=olist[counter].obstype;
+                obsstdlist[counter3].telsetup_std=olist[counter].telsetup;
+                obsstdlist[counter3].sourcekey_std=olist[counter].sourcekey;
+                obsstdlist[counter3].fluxweight_std=olist[counter].fluxweight;
+                obsstdlist[counter3].flux_std=olist[counter].flux;
+                obsstdlist[counter3].slope_std=olist[counter].slope;
+                obsstdlist[counter3].ra_std=olist[counter].ra;
+                obsstdlist[counter3].dec_std=olist[counter].dec;
                 counter3++;
             }
@@ -247,12 +427,82 @@
         cout << obsstdlist.size() << " standard observations found. " << endl;
 
-        // in this loop the fixed observations shall be
-        // checked, evaluated and added to the ScheduledObs list
+        // loop to add the fixed observations to the ScheduledObs list
+        // missing: checks and evaluation
+        //  * check for sun
+        //  * check for moon
+        counter2=0;
+        boost::posix_time::ptime finalobsfixedstart;
+        boost::posix_time::ptime finalobsfixedstop;
+        boost::posix_time::time_duration delta1;
+        boost::posix_time::time_duration delta2;
+        boost::posix_time::time_duration delta0(0,0,0);
         struct vector<FixedObs>::iterator vobs;
+        struct vector<FixedObs>::iterator vobs5;
         cout << "Fixed Observations: " << endl;
         for (vobs=obsfixedlist.begin(); vobs!=obsfixedlist.end(); vobs++)
         {
-            cout << "  " << (*vobs).sourcename_fixed <<  " " << (*vobs).obsfixedstart << flush;
-            cout << " - " << (*vobs).obsfixedstop << endl;
+            counter3=0;
+            delta1=delta0;
+            delta2=delta0;
+            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
+                    && obsfixedlist[counter2].obsfixedstart <= (*vobs5).obsfixedstart
+                    && 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
+                    && obsfixedlist[counter2].obsfixedstop >= (*vobs5).obsfixedstop
+                    && counter2!=counter3)
+                {
+                    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.";
+                    T::Warn(warndelta2);
+                }
+                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;
+            counter2++;
+            //cout << "  " << (*vobs).sourcename_fixed <<  " " << (*vobs).obsfixedstart << flush;
+            //cout << " - " << (*vobs).obsfixedstop << endl;
         }
 
@@ -270,10 +520,78 @@
         // in this loop from the scheduled observations the list
         // of scheduled runs shall be calculated
+        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;
+            runlist[counter2].runstop=obslist[counter2].obsstop;
+            runlist[counter2].sourcename_run=obslist[counter2].sourcename_obs;
+            runlist[counter2].obsmode_run=obslist[counter2].obsmode_obs;
+            runlist[counter2].obstype_run=obslist[counter2].obstype_obs;
+            runlist[counter2].telsetup_run=obslist[counter2].telsetup_obs;
+            runlist[counter2].sourcekey_run=obslist[counter2].sourcekey_obs;
+            counter2++;
             cout << (*vobs3).sourcename_obs << endl;
         }
 
+        //delete old scheduled runs from the DB
+        mysqlpp::Query query0 = conn.query("DELETE FROM ScheduledRun");
+
+        mysqlpp::SimpleResult res0 = query0.execute();
+        if (!res0)
+        {
+            cout << "MySQL query failed: " << query0.error() << endl;
+            throw;
+        }
+
+        counter3=0;
+        boost::posix_time::ptime finalstarttime;
+        boost::posix_time::ptime finalstoptime;
+        struct vector<ScheduledRun>::iterator vobs4;
+        for (vobs4=runlist.begin(); vobs4!=runlist.end(); vobs4++)
+        {
+            for (int i=2; i<5; i++)
+            {
+                switch(i)
+                {
+                case 2:
+                    finalstarttime=runlist[counter3].runstart+repostime+runtimec+runtimep;
+                    finalstoptime=runlist[counter3].runstop;
+                    break;
+                case 3:
+                    finalstarttime=runlist[counter3].runstart+repostime;
+                    finalstoptime=runlist[counter3].runstart+runtimep+repostime;
+                    break;
+                case 4:
+                    finalstarttime=runlist[counter3].runstart+runtimep+repostime;
+                    finalstoptime=runlist[counter3].runstart+repostime+runtimep+runtimec;
+                    break;
+                }
+                stringstream q1;
+                //cout << (*vobs4).sourcename_run << endl;
+                q1 << "INSERT ScheduledRun set fStartTime='" << Time::sql << finalstarttime;
+                q1 << "', fStopTime='" << Time::sql << finalstoptime;
+                q1 << "', fSourceKEY='" << (*vobs4).sourcekey_run;
+                q1 << "', fRunTypeKEY='" << i;
+                q1 << "', fTelescopeSetupKEY='" << (*vobs4).telsetup_run;
+                q1 << "', fObservationTypeKEY='" << (*vobs4).obstype_run;
+                q1 << "', fObservationModeKEY='" << (*vobs4).obsmode_run;
+                q1 << "'";
+
+                //cout << "executing query: " << q1.str() << endl;
+
+                mysqlpp::Query query1 = conn.query(q1.str());
+
+                mysqlpp::SimpleResult res1 = query1.execute();
+                if (!res1)
+                {
+                    cout << "MySQL query failed: " << query1.error() << endl;
+                    throw;
+                }
+            }
+            counter3++;
+        }
         //usleep(3000000);
         T::Message("Scheduling done.");
