Index: trunk/FACT++/src/scheduler.cc
===================================================================
--- trunk/FACT++/src/scheduler.cc	(revision 19508)
+++ trunk/FACT++/src/scheduler.cc	(revision 19516)
@@ -426,14 +426,41 @@
     uint16_t fKeepAliveInterval;
 
-    int16_t GetSourceKey(const string &name, const double &ra, const double &dec)
+    struct Source
+    {
+        int16_t key { -1 };
+        bool isToO { false };
+    };
+
+    Source GetSourceKey(const string &name, const double &ra, const double &dec)
     {
         const double min_dist   = 0.1;
         const double check_dist = 2.0;
 
-
-        int32_t source_key = -1;
+        // ----------------------- Check if source with same name exists -----------------------
+
+        const string query2 =
+            "SELECT fSourceKey, fIsToO FROM Source WHERE fSourceName='"+name+"'";
+
+        const mysqlpp::StoreQueryResult res2 = fConnection.query(query2).store();
+
+        if (res2.num_rows())
+        {
+            Source source;
+            source.key   = res2[0]["fSourceKey"];
+            source.isToO = res2[0]["fIsToO"];
+
+            Info("A source with the same name (key="+to_string(source.key)+") was found in the Source table.");
+
+            return source;
+        }
+
+        // ----------------- Check if source with similar coordinates exists -------------------
 
         const string query1 =
-            "SELECT fSourceKey, fSourceName, ADIST(fDeclination, fRightAscension*15, "+to_string(dec)+", "+to_string(ra)+") AS Dist\n"
+            "SELECT\n"
+            "   fSourceKey,\n"
+            "   fSourceName,\n"
+            "   ADIST(fDeclination, fRightAscension*15, "+to_string(dec)+", "+to_string(ra)+") AS Dist,\n"
+            "   fIsToO\n"
             " FROM Source\n"
             " WHERE fSourceTypeKEY=1\n"
@@ -445,10 +472,10 @@
         if (res1.num_rows())
         {
-            Info("Found "+to_string(res1.num_rows())+" sources with a distance less than "+to_string(check_dist)+"\u00b0");
+            Info("Found "+to_string(res1.num_rows())+" sources with a distance less than "+Tools::Form("%.2f", check_dist)+"\u00b0");
 
             for (size_t i=0; i<res1.num_rows(); i++)
             {
                 const mysqlpp::Row &row = res1[i];
-                Info(" "+string(row["fSourceName"])+" ["+string(row["fSourceKey"])+"]: D="+string(row["Dist"])+"\u00b0");
+                Info(" "+string(row["fSourceName"])+" ["+string(row["fSourceKey"])+"]: D="+Tools::Form("%.2f", double(row["Dist"]))+"\u00b0");
             }
 
@@ -456,24 +483,16 @@
             if (double(row["Dist"])<min_dist)
             {
-                Warn("Sources closer than "+to_string(check_dist)+"\u00b0 detected.");
-                Warn("Overwriting source key with: "+string(row["fSourceName"])+" ["+string(row["fSourceKey"])+"]: D="+string(row["Dist"])+"\u00b0");
-                source_key = res1[0]["fSourceKey"];
+                Source source;
+                source.key   = res1[0]["fSourceKey"];
+                source.isToO = res1[0]["fIsToO"];
+
+                Warn("Sources closer than "+Tools::Form("%.2f", check_dist)+"\u00b0 detected.");
+                Warn("Overwriting source key with: "+string(row["fSourceName"])+" ["+to_string(source.key)+"]: D="+Tools::Form("%.2f", double(row["Dist"]))+"\u00b0");
+
+                return source;
             }
         }
 
-        //Out() << Time()-stopwatch << endl;
-
-        const string query2 =
-            "SELECT fSourceKey FROM Source WHERE fSourceName='"+name+"'";
-
-        const mysqlpp::StoreQueryResult res2 = fConnection.query(query2).store();
-
-        if (res2.num_rows())
-        {
-            source_key = res2[0]["fSourceKey"];
-            Info("A source with the same name (key="+to_string(source_key)+") was found in the Source table.");
-        }
-
-        return source_key;
+        return Source();
     }
 
@@ -575,5 +594,5 @@
 
 
-    bool ScheduleImp(const string &name, const double &ra, const double &dec, const bool &known_only)
+    bool ScheduleImp(const string &name, const double &ra, const double &dec, const CheckVisibility &check, const bool &is_pointing)
     {
         const bool fDryRun = GetCurrentState()!=ToO::State::kArmed;
@@ -608,12 +627,31 @@
          */
 
-        int32_t source_key = GetSourceKey(name, ra, dec);
+        Source source = GetSourceKey(name, ra, dec);
 
         Out() << Time()-stopwatch << endl;
 
-        if (known_only && source_key<0)
+        if (is_pointing && source.key<0) // Not a known source
         {
             Warn("Observation of only known sources requested but no known source found.");
             return false;
+        }
+
+        if (source.key>=0)
+        {
+            if (source.isToO)
+            {
+                Warn("Known source with ToO flag... skipping.");
+                return false;
+            }
+
+            const set<uint16_t> prioritized_sources = { 1, 2, 7 };
+
+            const bool prio = prioritized_sources.find(source.key)!=prioritized_sources.end();
+
+            if ((check.threshold>3 && !prio) || check.threshold>10)
+            {
+                Warn("Relative threshold too high... skipping.");
+                return false;
+            }
         }
 
@@ -690,4 +728,5 @@
         int32_t reschedule = -1;
         int32_t following  = -1;
+        int32_t last_resch = -1;
         for (size_t i=0; i<resS.num_rows(); i++)
         {
@@ -715,4 +754,7 @@
                 reschedule = i;
 
+            if (bool(row["Reschedule"]) && !row["Delete"])
+                last_resch = i;
+
             if (following==-1 && bool(row["Following"]))
                 following = i;
@@ -799,9 +841,5 @@
         // ====================================================================
 
-        // FIXME: Check if source is not already scheduled anyways
-
-        Info("Source will be scheduled.");
-
-        if (source_key<0)
+        if (source.key<0)
         {
             const double wobble_angle = GetWobbleAngle(ra, dec);
@@ -818,13 +856,13 @@
                 auto q = fConnection.query(query);
                 q.execute();
-                Info(q.info());
-
-                source_key = q.insert_id();
-
-                Info(string(fDryRun?"[dry-run] ":"")+"The new source got the key "+to_string(source_key));
+                if (!q.info().empty())
+                    Info(q.info());
+
+                source.key = q.insert_id();
+
+                Info(string(fDryRun?"[dry-run] ":"")+"The new source got the key "+to_string(source.key));
             }
             else
                 Out() << query << endl;
-
         }
 
@@ -833,10 +871,19 @@
         // ====================================================================
 
+        Info("Source will be scheduled.");
+
+        Out() << "New entries:\n";
+
         vector<string> insert;
 
-        Out() << "New entries:\n";
-        Out() << "           | auto  | " << schedtime.GetAsStr()     << " |       < start >     | 0 | ToO  | nodrs,grb | " << setw(4) << source_key << " | 4\n";
-
-        insert.emplace_back("('"+schedtime.GetAsStr()+"',0,'ToO','nodrs:true,grb:true',"+to_string(source_key)+",4)");
+        const bool ongoing = last_resch>=0 && source.key==uint16_t(resS[last_resch]["fSourceKey"]);
+
+        if (ongoing)
+            Out() << "           |       |                     |      < ongoing >    | 0 |      |           | " << setw(4) << source.key << " | 4\n";
+        else
+        {
+            Out() << "           | auto  | " << schedtime.GetAsStr()     << " |       < start >     | 0 | ToO  | " << (is_pointing?"  nodrs  ":"nodrs,grb") << " | " << setw(4) << source.key << " | 4\n";
+            insert.emplace_back("('"+schedtime.GetAsStr()+"',0,'ToO','"+(is_pointing?"nodrs:true":"nodrs:true,grb:true")+"',"+to_string(source.key)+",4)");
+        }
 
         // --------------------------------------------------------------------
@@ -878,5 +925,6 @@
         // Empty interrupt to stop data taking as early as possible
         // Triggers also RELOAD_SOURCES
-        Dim::SendCommandNB("DIM_CONTROL/INTERRUPT", "prepare");
+        if (!ongoing)
+            Dim::SendCommandNB("DIM_CONTROL/INTERRUPT", "prepare");
 
         // ---------------------------------------------------------
@@ -897,5 +945,6 @@
             auto q = fConnection.query(queryI);
             q.execute();
-            Info(q.info());
+            if (!q.info().empty())
+                Info(q.info());
         }
         // ---------------------------------------------------------
@@ -905,5 +954,6 @@
         // ---------------------------------------------------------
 
-        Dim::SendCommand("DIM_CONTROL/INTERRUPT", "reschedule");
+        if (!ongoing)
+            Dim::SendCommand("DIM_CONTROL/INTERRUPT", "reschedule");
 
         ostringstream out;
@@ -914,9 +964,9 @@
     }
 
-    bool Schedule(const string &name, const double &ra, const double &dec, const bool &known_only)
+    bool Schedule(const string &name, const double &ra, const double &dec, const CheckVisibility &check, const bool &is_pointing)
     {
         try
         {
-            return ScheduleImp(name, ra, dec, known_only);
+            return ScheduleImp(name, ra, dec, check, is_pointing);
         }
         catch (const exception &e)
@@ -1018,8 +1068,11 @@
 
         Info(string("Sun altitude:   ")+(check.valid_sun      ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.solarobj.fSunHrz.alt)+"\u00b0]");
-        Info(string("Moon distance:  ")+(check.valid_moon     ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.moon_dist)+"\u00b0]");
-        Info(string("Zenith angle:   ")+(check.valid_zd       ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.position.zd)+"\u00b0]");
-        Info(string("Current:        ")+(check.valid_current  ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.current)+" \u00b5A]");
-        Info(string("Rel. threshold: ")+(check.valid_threshold?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.threshold)+"]");
+        if (check.valid_sun)
+        {
+            Info(string("Moon distance:  ")+(check.valid_moon     ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.moon_dist)+"\u00b0]");
+            Info(string("Zenith angle:   ")+(check.valid_zd       ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.position.zd)+"\u00b0]");
+            Info(string("Current:        ")+(check.valid_current  ?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.current)+" \u00b5A]");
+            Info(string("Rel. threshold: ")+(check.valid_threshold?"OK    ":"failed")+" ["+Tools::Form("%5.1f", check.threshold)+"]");
+        }
 
         if (!check.visible)
@@ -1094,7 +1147,7 @@
 */
 
-        const bool known_only = grb.type==51 || grb.type==83;
-
-        Schedule(name, grb.ra, grb.dec, known_only);
+        const bool is_pointing = grb.type==51 || grb.type==83;
+
+        Schedule(name, grb.ra, grb.dec, check, is_pointing);
 
         return fConnection.connected() ? GetCurrentState() : ToO::State::kDisconnected;
