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

KDE's Doxygen guidelines are available online.