Kstars

schedulerjob.h
1/* Ekos Scheduler Job
2 SPDX-FileCopyrightText: Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#pragma once
8
9#include "skypoint.h"
10#include "schedulertypes.h"
11#include "ekos/capture/sequencejob.h"
12#include "greedyscheduler.h"
13
14#include <QUrl>
15#include <QMap>
16#include "kstarsdatetime.h"
17#include <QJsonObject>
18
20class KSMoon;
21class TestSchedulerUnit;
22class TestEkosSchedulerOps;
23class dms;
24
25namespace Ekos
26{
27class SchedulerJob
28{
29 public:
30 SchedulerJob();
31
32 QJsonObject toJson() const;
33
34 /** @brief Actions that may be processed when running a SchedulerJob.
35 * FIXME: StepPipeLine is actually a mask, change this into a bitfield.
36 */
37 typedef enum
38 {
39 USE_NONE = 0,
40 USE_TRACK = 1 << 0,
41 USE_FOCUS = 1 << 1,
42 USE_ALIGN = 1 << 2,
43 USE_GUIDE = 1 << 3
44 } StepPipeline;
45
46 struct JobProgress
47 {
48 int numCompleted = 0;
49 CCDFrameType type;
50 bool isDarkFlat = false;
51 QMap<SequenceJob::PropertyID, QVariant> properties;
52 JobProgress() {}
53 JobProgress(int numCompleted, const QSharedPointer<SequenceJob> &job)
54 : numCompleted(numCompleted), type(job->getFrameType()),
55 isDarkFlat(job->jobType() == SequenceJob::JOBTYPE_DARKFLAT),
56 properties(job->getCoreProperties()) {};
57 };
58
59 /** @brief Coordinates of the target of this job. */
60 /** @{ */
61 SkyPoint const &getTargetCoords() const
62 {
63 if (m_LeadJob != nullptr)
64 return m_LeadJob->getTargetCoords();
65 else
66 return targetCoords;
67 }
68 void setTargetCoords(const dms &ra, const dms &dec, double djd);
69 /** @} */
70
71 double getPositionAngle()
72 {
73 return m_PositionAngle;
74 }
75 void setPositionAngle(double value);
76
77 /** @brief Capture sequence this job uses while running. */
78 /** @{ */
79 QUrl getSequenceFile() const
80 {
81 return sequenceFile;
82 }
83 void setSequenceFile(const QUrl &value);
84 /** @} */
85
86 /** @brief FITS file whose plate solve produces target coordinates. */
87 /** @{ */
88 QUrl getFITSFile() const
89 {
90 if (m_LeadJob != nullptr)
91 return m_LeadJob->getFITSFile();
92 else
93 return fitsFile;
94 }
95 void setFITSFile(const QUrl &value);
96 /** @} */
97
98 /** @brief Minimal target altitude to process this job */
99 /** @{ */
100 double getMinAltitude() const
101 {
102 if (m_LeadJob != nullptr)
103 return m_LeadJob->getMinAltitude();
104 else
105 return minAltitude;
106 }
107 void setMinAltitude(const double &value);
108 /** @} */
109
110 /** @brief Does this job have a min-altitude parameter. */
111 /** @{ */
112 bool hasMinAltitude() const
113 {
114 return UNDEFINED_ALTITUDE < getMinAltitude();
115 }
116 static constexpr int UNDEFINED_ALTITUDE = -90;
117 /** @} */
118
119 /** @brief Does this job have any altitude constraints. */
120 /** @{ */
121 bool hasAltitudeConstraint() const;
122 /** @} */
123
124 /** @brief Minimal Moon separation to process this job. */
125 /** @{ */
126 double getMinMoonSeparation() const
127 {
128 if (m_LeadJob != nullptr)
129 return m_LeadJob->getMinMoonSeparation();
130 else
131 return minMoonSeparation;
132 }
133 void setMinMoonSeparation(const double &value);
134 /** @} */
135
136 /** @brief Maximal moon altitude to process this job. */
137 /** @{ */
138 double getMaxMoonAltitude() const
139 {
140 if (m_LeadJob != nullptr)
141 return m_LeadJob->getMaxMoonAltitude();
142 else
143 return maxMoonAltitude;
144 }
145 void setMaxMoonAltitude(const double &value);
146 /** @} */
147
148 /** @brief Mask of actions to process for this job. */
149 /** @{ */
150 StepPipeline getStepPipeline() const
151 {
152 if (m_LeadJob != nullptr)
153 return m_LeadJob->getStepPipeline();
154 else
155 return stepPipeline;
156 }
157 void setStepPipeline(const StepPipeline &value);
158 /** @} */
159
160 /** @brief Condition under which this job starts. */
161 /** @{ */
162 StartupCondition getStartupCondition() const
163 {
164 if (m_LeadJob != nullptr)
165 return m_LeadJob->getStartupCondition();
166 else
167 return startupCondition;
168 }
169 void setStartupCondition(const StartupCondition &value);
170 /** @} */
171
172 /** @brief Condition under which this job completes. */
173 /** @{ */
174 CompletionCondition getCompletionCondition() const
175 {
176 return completionCondition;
177 }
178 void setCompletionCondition(const CompletionCondition &value);
179 /** @} */
180
181 /** @brief Original startup condition, as entered by the user. */
182 /** @{ */
183 StartupCondition getFileStartupCondition() const
184 {
185 if (m_LeadJob != nullptr)
186 return m_LeadJob->getFileStartupCondition();
187 else
188 return fileStartupCondition;
189 }
190 void setFileStartupCondition(const StartupCondition &value);
191 /** @} */
192
193 /** @brief Original time at which the job must start, as entered by the user. */
194 /** @{ */
195 QDateTime getStartAtTime() const
196 {
197 if (m_LeadJob != nullptr)
198 return m_LeadJob->getStartAtTime();
199 else
200 return startAtTime;
201 }
202 void setStartAtTime(const QDateTime &value);
203 /** @} */
204
205 /** @brief Whether this job requires re-focus while running its capture sequence. */
206 /** @{ */
207 bool getInSequenceFocus() const
208 {
209 return inSequenceFocus;
210 }
211 void setInSequenceFocus(bool value);
212 /** @} */
213
214 /** @brief Whether to restrict job to night time. */
215 /** @{ */
216 bool getEnforceTwilight() const
217 {
218 if (m_LeadJob != nullptr)
219 return m_LeadJob->getEnforceTwilight();
220 else
221 return enforceTwilight;
222 }
223 void setEnforceTwilight(bool value);
224 /** @} */
225
226 /** @brief Whether to restrict job to night time. */
227 /** @{ */
228 bool getEnforceArtificialHorizon() const
229 {
230 if (m_LeadJob != nullptr)
231 return m_LeadJob->getEnforceArtificialHorizon();
232 else
233 return enforceArtificialHorizon;
234 }
235 void setEnforceArtificialHorizon(bool value);
236 /** @} */
237
238 /** @brief Current name of the scheduler job. */
239 /** @{ */
240 QString getName() const
241 {
242 if (m_LeadJob != nullptr)
243 return m_LeadJob->getName();
244 else
245 return name;
246 }
247 void setName(const QString &value);
248 /** @} */
249
250 /** @brief Flag if the scheduler job is a lead job with its own target or if it is a follower job to another lead job. */
251 /** @{ */
252 bool isLead() const
253 {
254 return m_isLead;
255 }
256 void setIsLead(bool value)
257 {
258 m_isLead = value;
259 }
260 /** @} */
261
262 /** @brief Group the scheduler job belongs to. */
263 /** @{ */
264 QString getGroup() const
265 {
266 if (m_LeadJob != nullptr)
267 return m_LeadJob->getGroup();
268 else
269 return group;
270 }
271 void setGroup(const QString &value);
272 /** @} */
273
274 /** @brief Optical train the scheduler job will be using. */
275 /** @{ */
276 QString getOpticalTrain() const
277 {
278 return opticalTrain;
279 }
280 void setOpticalTrain(const QString &value)
281 {
282 opticalTrain = value;
283 }
284 /** @} */
285
286 /** @brief Iteration the scheduler job has achieved. This only makes sense for jobs that repeat. */
287 /** @{ */
288 int getCompletedIterations() const
289 {
290 return completedIterations;
291 }
292 void setCompletedIterations(int value);
293 /** @} */
294
295 /** @brief Current state of the scheduler job.
296 * Setting state to JOB_ABORTED automatically resets the startup characteristics.
297 * Setting state to JOB_INVALID automatically resets the startup characteristics and the duration estimation.
298 * @see SchedulerJob::setStartupCondition, SchedulerJob::setFileStartupCondition, SchedulerJob::setStartupTime
299 * and SchedulerJob::setFileStartupTime.
300 */
301 /** @{ */
302 SchedulerJobStatus getState() const
303 {
304 return state;
305 }
306
307 /**
308 * @brief isStopped helper function for idle or aborted state
309 */
310 bool isStopped() const
311 {
312 return (state == SCHEDJOB_IDLE || state == SCHEDJOB_ABORTED);
313 }
314 QDateTime getStateTime() const
315 {
316 return stateTime;
317 }
318 QDateTime getLastAbortTime() const
319 {
320 return lastAbortTime;
321 }
322 QDateTime getLastErrorTime() const
323 {
324 return lastErrorTime;
325 }
326 void setState(const SchedulerJobStatus &value, bool force = false);
327
328 void setFollowerState(const SchedulerJobStatus &value, bool force);
329
330 /**
331 * @brief Update the attributes of all followers that are shared with the lead job
332 */
333 void updateSharedFollowerAttributes();
334 /** @} */
335
336 /** @brief Current stage of the scheduler job. */
337 /** @{ */
338 SchedulerJobStage getStage() const
339 {
340 return stage;
341 }
342 void setStage(const SchedulerJobStage &value);
343 /** @} */
344
345 /** @brief Number of captures required in the associated sequence. */
346 /** @{ */
347 int getSequenceCount() const
348 {
349 return sequenceCount;
350 }
351 void setSequenceCount(const int count);
352 /** @} */
353
354 /** @brief Number of captures completed in the associated sequence. */
355 /** @{ */
356 int getCompletedCount() const
357 {
358 return completedCount;
359 }
360 void setCompletedCount(const int count);
361 /** @} */
362
363 /** @brief Time at which the job must start. */
364 /** @{ */
365 QDateTime getStartupTime() const
366 {
367 return startupTime;
368 }
369 void setStartupTime(const QDateTime &value, bool refreshDawnDusk = true);
370 /** @} */
371
372 /** @brief Time after which the job is considered to finish. */
373 /** @{ */
374 QDateTime getFinishAtTime() const
375 {
376 return finishAtTime;
377 }
378 QDateTime getStopTime() const
379 {
380 return stopTime;
381 }
382 const QString &getStopReason() const
383 {
384 return stopReason;
385 }
386 void setStopReason(const QString &reason)
387 {
388 stopReason = reason;
389 }
390 void setFinishAtTime(const QDateTime &value);
391 /** @} */
392 void setStopTime(const QDateTime &value);
393
394 /** @brief Estimation of the time the job will take to process. */
395 /** @{ */
396 int64_t getEstimatedTime() const
397 {
398 return estimatedTime;
399 }
400 void setEstimatedTime(const int64_t &value);
401 /** @} */
402
403 /** @brief Estimation of the time the job will take to process each repeat. */
404 /** @{ */
405 int64_t getEstimatedTimePerRepeat() const
406 {
407 return estimatedTimePerRepeat;
408 }
409 void setEstimatedTimePerRepeat(const int64_t &value)
410 {
411 estimatedTimePerRepeat = value;
412 }
413
414 /** @brief Estimation of the time the job will take at startup. */
415 /** @{ */
416 int64_t getEstimatedStartupTime() const
417 {
418 if (m_LeadJob != nullptr)
419 return m_LeadJob->getEstimatedStartupTime();
420 else
421 return estimatedStartupTime;
422 }
423 void setEstimatedStartupTime(const int64_t &value)
424 {
425 estimatedStartupTime = value;
426 }
427
428 /** @brief Estimation of the time the job will take to process each repeat. */
429 /** @{ */
430 int64_t getEstimatedTimeLeftThisRepeat() const
431 {
432 return estimatedTimeLeftThisRepeat;
433 }
434 void setEstimatedTimeLeftThisRepeat(const int64_t &value)
435 {
436 estimatedTimeLeftThisRepeat = value;
437 }
438
439 /** @brief Whether this job requires light frames, or only calibration frames. */
440 /** @{ */
441 bool getLightFramesRequired() const
442 {
443 return lightFramesRequired;
444 }
445 void setLightFramesRequired(bool value);
446 /** @} */
447
448 /** @brief Whether this job contains a calibration job that requires mount parking. */
449 /** @{ */
450 bool getCalibrationMountPark() const
451 {
452 return m_CalibrationMountPark;
453 }
454 void setCalibrationMountPark(bool value);
455 /** @} */
456
457 /** @brief Number of times this job must be repeated (in terms of capture count). */
458 /** @{ */
459 uint16_t getRepeatsRequired() const
460 {
461 return repeatsRequired;
462 }
463 void setRepeatsRequired(const uint16_t &value);
464 /** @} */
465
466 /** @brief Number of times this job still has to be repeated (in terms of capture count). */
467 /** @{ */
468 uint16_t getRepeatsRemaining() const
469 {
470 return repeatsRemaining;
471 }
472 void setRepeatsRemaining(const uint16_t &value);
473 /** @} */
474
475 void clearProgress()
476 {
477 m_Progress.clear();
478 }
479 void addProgress(int numCompleted, const QSharedPointer<SequenceJob> &job)
480 {
481 m_Progress.append(JobProgress(numCompleted, job));
482 }
483 /** @brief Human-readable summary of captures completed for this job. */
484 /** @{ */
485 const QString getProgressSummary() const;
486 /** @} */
487
488 /** @brief The map of capture counts for this job, keyed by its capture storage signatures. */
489 /** @{ */
490 const CapturedFramesMap &getCapturedFramesMap() const
491 {
492 return capturedFramesMap;
493 }
494 void setCapturedFramesMap(const CapturedFramesMap &value);
495 /** @} */
496
497 /** @brief Resetting a job to original values:
498 * - idle state and stage
499 * - original startup, none if asap, else user original setting
500 * - duration not estimated
501 * - full repeat count
502 */
503 void reset();
504
505 /** @brief Determining whether a SchedulerJob is a duplicate of another.
506 * @param a_job is the other SchedulerJob to test duplication against.
507 * @return True if objects are different, but name and sequence file are identical, else false.
508 * @warning This is a weak comparison, but that's what the scheduler looks at to decide completion.
509 */
510 bool isDuplicateOf(SchedulerJob const *a_job) const
511 {
512 return this != a_job && name == a_job->getName() && sequenceFile == a_job->sequenceFile;
513 }
514
515 /** @brief Compare ::SchedulerJob instances based on altitude and movement in sky at startup time.
516 * @todo This is a qSort predicate, deprecated in QT5.
517 * @arg a, b are ::SchedulerJob instances to compare.
518 * @arg when is the date/time to use to calculate the altitude to sort with, defaulting to a's startup time.
519 * @note To obtain proper sort between several SchedulerJobs, all should have the same startup time.
520 * @note Use std:bind to bind a specific date/time to this predicate for altitude calculation.
521 * @return true is a is setting but not b.
522 * @return false if b is setting but not a.
523 * @return true otherwise, if the altitude of b is lower than the altitude of a.
524 * @return false otherwise, if the altitude of b is higher than or equal to the altitude of a.
525 */
526 static bool decreasingAltitudeOrder(SchedulerJob const *a, SchedulerJob const *b, QDateTime const &when = QDateTime());
527
528 /**
529 * @brief moonConstraintsOK return true if angle from target to the Moon is > minMoonSeparation and
530 * the moon's altitude is below the given value.
531 * @param when date and time to check the Moon separation, now if omitted.
532 * @param reason pointer to the reason text in case that the check failed
533 * @return true if target is separated enough from the Moon.
534 */
535 bool moonConstraintsOK(QDateTime const &when = QDateTime(), QString *reason = new QString(),
536 double *margin = nullptr) const;
537
538 /**
539 * @brief calculateNextTime calculate the next time constraints are met (or missed).
540 * @param when date and time to start searching from, now if omitted.
541 * @param constraintsAreMet if true, searches for the next time constrains are met, else missed.
542 * @return The date and time the target meets or misses constraints.
543 */
544 QDateTime calculateNextTime(QDateTime const &when, bool checkIfConstraintsAreMet = true, int increment = 1,
545 QString *reason = nullptr, bool runningJob = false, const QDateTime &until = QDateTime()) const;
546 QDateTime getNextPossibleStartTime(const QDateTime &when, int increment = 1, bool runningJob = false,
547 const QDateTime &until = QDateTime()) const;
548 QDateTime getNextEndTime(const QDateTime &start, int increment = 1, QString *reason = nullptr,
549 const QDateTime &until = QDateTime()) const;
550 bool checkAltitudeAndMoon(SkyObject o, const KStarsDateTime &ltOffset, QString *reason, double *margin) const;
551
552
553 /**
554 * @brief getNextAstronomicalTwilightDawn
555 * @return a local time QDateTime locating the first astronomical dawn after this observation.
556 * @note The dawn time takes into account the Ekos dawn offset.
557 */
558 QDateTime getDawnAstronomicalTwilight() const
559 {
560 if (m_LeadJob != nullptr)
561 return m_LeadJob->getDawnAstronomicalTwilight();
562 else
563 return nextDawn;
564 };
565
566 /**
567 * @brief getDuskAstronomicalTwilight
568 * @return a local-time QDateTime locating the first astronomical dusk after this observation.
569 * @note The dusk time takes into account the Ekos dusk offset.
570 */
571 QDateTime getDuskAstronomicalTwilight() const
572 {
573 if (m_LeadJob != nullptr)
574 return m_LeadJob->getDuskAstronomicalTwilight();
575 else
576 return nextDusk;
577 };
578
579 /**
580 * @brief runsDuringAstronomicalNightTime
581 * @param time uses the time given for the check, or, if not valid (the default) uses the job's startup time.
582 * @return true if the next dawn/dusk event after this observation is the astronomical dawn, else false.
583 * @note This function relies on the guarantee that dawn and dusk are calculated to be the first events after this observation.
584 */
585 bool runsDuringAstronomicalNightTime(const QDateTime &time = QDateTime(), QDateTime *nextPossibleSuccess = nullptr) const;
586
587 /**
588 * @brief satisfiesAltitudeConstraint sees if altitude is allowed for this job at the given azimuth.
589 * @param azimuth Azimuth
590 * @param altitude Altitude
591 * @param altitudeReason a human-readable string explaining why false was returned.
592 * @return true if this altitude is permissible for this job
593 */
594 bool satisfiesAltitudeConstraint(double azimuth, double altitude, QString *altitudeReason = nullptr,
595 double *margin = nullptr) const;
596
597 /**
598 * @brief setInitialFilter Set initial filter used in the capture sequence. This is used to pass to focus module.
599 * @param value Filter name of FIRST LIGHT job in the sequence queue, if any.
600 */
601 void setInitialFilter(const QString &value);
602 const QString &getInitialFilter() const;
603
604 // Convenience debugging methods.
605 static QString jobStatusString(SchedulerJobStatus status);
606 static QString jobStageString(SchedulerJobStage stage);
607 QString jobStartupConditionString(StartupCondition condition) const;
608 QString jobCompletionConditionString(CompletionCondition condition) const;
609
610 // Clear the cache that keeps results for getNextPossibleStartTime().
611 void clearCache()
612 {
613 startTimeCache.clear();
614 }
615 double getAltitudeAtStartup() const
616 {
617 if (m_LeadJob != nullptr)
618 return m_LeadJob->getAltitudeAtStartup();
619 else
620 return altitudeAtStartup;
621 }
622 double getAltitudeAtStop() const
623 {
624 return altitudeAtStop;
625 }
626 bool isSettingAtStartup() const
627 {
628 if (m_LeadJob != nullptr)
629 return m_LeadJob->isSettingAtStartup();
630 else
631 return settingAtStartup;
632 }
633 bool isSettingAtStop() const
634 {
635 return settingAtStop;
636 }
637
638 SchedulerJob *leadJob() const
639 {
640 return m_LeadJob;
641 }
642 void setLeadJob(SchedulerJob *newLeadJob)
643 {
644 m_LeadJob = newLeadJob;
645 }
646
647 QList<SchedulerJob *> &followerJobs()
648 {
649 return m_followerJobs;
650 }
651
652 void setStartupFormatted(const QString &value)
653 {
654 m_StartupFormatted = value;
655 }
656 const QString &startupFormatted() const
657 {
658 return m_StartupFormatted;
659 }
660
661 void setEndFormatted(const QString &value)
662 {
663 m_EndFormatted = value;
664 }
665 const QString &endFormatted() const
666 {
667 return m_EndFormatted;
668 }
669
670 void setAltitudeFormatted(const QString &value)
671 {
672 m_AltitudeFormatted = value;
673 }
674 const QString &altitudeFormatted() const
675 {
676 return m_AltitudeFormatted;
677 }
678
679 void clearSimulatedSchedule()
680 {
681 m_SimulatedSchedule.clear();
682 }
683 void setSimulatedSchedule(const QList<GreedyScheduler::JobSchedule> &schedule)
684 {
685 m_SimulatedSchedule = schedule;
686 }
687 void appendSimulatedSchedule(const GreedyScheduler::JobSchedule &jobSchedule)
688 {
689 m_SimulatedSchedule.append(jobSchedule);
690 }
691 const QList<GreedyScheduler::JobSchedule> &getSimulatedSchedule() const
692 {
693 return m_SimulatedSchedule;
694 }
695
696 private:
697 bool runsDuringAstronomicalNightTimeInternal(const QDateTime &time, QDateTime *minDawnDusk,
698 QDateTime *nextPossibleSuccess = nullptr) const;
699
700 // Private constructor for unit testing.
701 SchedulerJob(KSMoon *moonPtr);
702 friend TestSchedulerUnit;
703 friend TestEkosSchedulerOps;
704
705 /** @brief Setter used in the unit test to fix the local time. Otherwise getter gets from KStars instance. */
706 /** @{ */
707 static KStarsDateTime getLocalTime();
708 /** @} */
709
710 /** @brief Setter used in testing to fix the artificial horizon. Otherwise getter gets from KStars instance. */
711 /** @{ */
712 static const ArtificialHorizon *getHorizon();
713 static void setHorizon(ArtificialHorizon *horizon)
714 {
715 storedHorizon = horizon;
716 }
717 static bool hasHorizon()
718 {
719 return storedHorizon != nullptr;
720 }
721
722 /** @} */
723
724 QString name;
725 bool m_isLead { true };
726 QString group;
727 QString opticalTrain;
728 int completedIterations { 0 };
729 SkyPoint targetCoords;
730 double m_PositionAngle { -1 };
732 SchedulerJobStage stage { SCHEDSTAGE_IDLE };
733
734 // leader / follower relationship
735 SchedulerJob *m_LeadJob { nullptr };
736 QList <SchedulerJob *> m_followerJobs;
737
738 // The time that the job stage was set.
739 // Used by the Greedy Algorithm to decide when to run JOB_ABORTED jobs again.
740 QDateTime stateTime;
741 QDateTime lastAbortTime;
742 QDateTime lastErrorTime;
743
744 StartupCondition fileStartupCondition { START_ASAP };
745 StartupCondition startupCondition { START_ASAP };
746 CompletionCondition completionCondition { FINISH_SEQUENCE };
747
748 int sequenceCount { 0 };
749 int completedCount { 0 };
750
751 // Defined startup time, used for the StartupCondition START_AT.
752 QDateTime startAtTime;
753 // Startup time calculated by the scheduler.
754 QDateTime startupTime;
755 // Completion constraint when the job must finish, used for the CompletionCondition FINISH_AT.
756 QDateTime finishAtTime;
757 // Next time when the scheduler will stop the job, either because its
758 // completed, its constraints aren't met or another job has higher priority.
759 QDateTime stopTime;
760 // The reason this job is stopping/will-be stopped.
761 QString stopReason;
762
763 /* @internal Caches to optimize cell rendering. */
764 /* @{ */
765 double altitudeAtStartup { 0 };
766 double altitudeAtStop { 0 };
767 bool settingAtStartup { false };
768 bool settingAtStop { false };
769 /* @} */
770
771 QUrl sequenceFile;
772 QUrl fitsFile;
773
774 double minAltitude { UNDEFINED_ALTITUDE };
775 double minMoonSeparation { -1 };
776 double maxMoonAltitude { 90 };
777
778 bool enforceTwilight { false };
779 bool enforceArtificialHorizon { false };
780
781 QDateTime nextDawn;
782 QDateTime nextDusk;
783
784 StepPipeline stepPipeline { USE_NONE };
785
786 int64_t estimatedTime { -1 };
787 int64_t estimatedTimePerRepeat { 0 };
788 int64_t estimatedStartupTime { 0 };
789 int64_t estimatedTimeLeftThisRepeat { 0 };
790 uint16_t repeatsRequired { 1 };
791 uint16_t repeatsRemaining { 1 };
792 bool inSequenceFocus { false };
793 QString m_InitialFilter;
794
795 QString dateTimeDisplayFormat;
796
797 QString m_StartupFormatted, m_EndFormatted, m_AltitudeFormatted;
798
799 bool lightFramesRequired { false };
800 bool m_CalibrationMountPark {false};
801
802 CapturedFramesMap capturedFramesMap;
803
804 /// Pointer to Moon object
805 KSMoon *moon { nullptr };
806
807 // Used to display human-readable job progress.
808 QList<JobProgress> m_Progress;
809
810 // An estimate as to when this job might run.
811 QList<GreedyScheduler::JobSchedule> m_SimulatedSchedule;
812
813 // This class is used to cache the results computed in getNextPossibleStartTime()
814 // which is called repeatedly by the Greedy scheduler.
815 // The cache would need to be cleared if something changes that would affect the
816 // start time of jobs (geography, altitide constraints) so it is reset at the start
817 // of all schedule calculations--which does not impact its effectiveness.
818 class StartTimeCache
819 {
820 // Keep track of calls to getNextPossibleStartTime, storing the when, until and result.
821 struct StartTimeComputation
822 {
823 QDateTime from;
824 QDateTime until;
825 QDateTime result;
826 };
827 public:
828 StartTimeCache() {}
829 // Check if the computation has been done, and if so, return the previous result.
830 bool check(const QDateTime &from, const QDateTime &until,
831 QDateTime *result, QDateTime *newFrom) const;
832 // Add a result to the cache.
833 void add(const QDateTime &from, const QDateTime &until, const QDateTime &result) const;
834 // Clear the cache.
835 void clear() const;
836 private:
837 // Made this mutable and all methods const so that the cache could be
838 // used in SchedulerJob const methods.
839 mutable QList<StartTimeComputation> startComputations;
840 };
841 StartTimeCache startTimeCache;
842
843 // These are used in testing, instead of KStars::Instance() resources
844 static KStarsDateTime *storedLocalTime;
845 static GeoLocation *storedGeo;
846 static ArtificialHorizon *storedHorizon;
847};
848} // Ekos namespace
Represents custom area from the horizon upwards which represent blocked views from the vantage point ...
Provides necessary information about the Moon.
Definition ksmoon.h:26
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
SchedulerJobStage
Running stages of a SchedulerJob.
StartupCondition
Conditions under which a SchedulerJob may start.
SchedulerJobStatus
States of a SchedulerJob.
@ SCHEDJOB_ABORTED
Job encountered a transitory issue while processing, and will be rescheduled.
@ SCHEDJOB_IDLE
Job was just created, and is not evaluated yet.
QMap< QString, uint16_t > CapturedFramesMap
mapping signature --> frames count
CompletionCondition
Conditions under which a SchedulerJob may complete.
void append(QList< T > &&value)
void clear()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Mar 28 2025 11:57:24 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.