Ver código fonte

Random Flight Generator

Added a class that generates random flights for testing purposes
Felix Turowsky 2 anos atrás
pai
commit
2297a1d81f

+ 2 - 0
CMakeLists.txt

@@ -133,6 +133,8 @@ set(PROJECT_SOURCES
     src/testing/importCrewlounge/processflights.cpp
     src/testing/atimer.h
     src/testing/atimer.cpp
+    src/testing/randomgenerator.h
+    src/testing/randomgenerator.cpp
 )
 
 # This is currently a bit buggy, see

BIN
assets/database/logbook.db


+ 0 - 4
main.cpp

@@ -33,10 +33,6 @@
 #include <QDebug>
 #include <QTranslator>
 
-#define APPNAME QStringLiteral("openPilotLog")
-#define ORGNAME QStringLiteral("opl")
-#define ORGDOMAIN QStringLiteral("https://github.com/fiffty-50/openpilotlog")
-
 /*!
  *  Helper functions that prepare and set up the application
  */

+ 6 - 9
mainwindow.cpp

@@ -25,18 +25,15 @@
 #include "src/gui/dialogues/newsimdialog.h"
 #include "src/gui/dialogues/newflightdialog.h"
 // Quick and dirty Debug area
-#include "src/classes/paths.h"
+#include "src/testing/randomgenerator.h"
 void MainWindow::doDebugStuff()
 {
-    DEB << OPL::Paths::directory(OPL::Paths::Backup);
-    DEB << OPL::Paths::path(OPL::Paths::Backup);
-    DEB << OPL::Paths::filePath(OPL::Paths::Database, "logbook.db");
-    DEB << OPL::Paths::setup();
+    auto generator = OPL::RandomGenerator();
+    OPL::FlightEntry entry = generator.randomFlight();
+    DB->commit(entry);
 
-    QDir dir(QCoreApplication::applicationDirPath());
-    QString filename("file.f");
-
-    DEB << OPL::Paths::filePath(OPL::Paths::Backup, filename);
+    auto nfd = NewFlightDialog(completionData, DB->getLastEntry(OPL::DbTable::Flights));
+    nfd.exec();
 }
 
 MainWindow::MainWindow(QWidget *parent)

+ 1 - 1
src/database/row.cpp

@@ -38,7 +38,7 @@ Row::Row(OPL::DbTable table_name, int row_id, const RowData_T &row_data)
     hasData = true;
 };
 
-RowData_T Row::getData() const
+const RowData_T &Row::getData() const
 {
     return rowData;
 }

+ 9 - 3
src/database/row.h

@@ -53,7 +53,7 @@ public:
     Row(const Row&) = default;
     Row& operator=(const Row&) = default;
 
-    RowData_T getData() const;
+    const RowData_T& getData() const;
     void setData(const RowData_T &value);
     int getRowId() const;
     void setRowId(int value);
@@ -99,8 +99,8 @@ public:
     TailEntry(const RowData_T &row_data);
     TailEntry(int row_id, const RowData_T &row_data);
 
-    const QString registration() const;
-    const QString type() const;
+    const QString registration() const { return getData().value(OPL::Db::TAILS_REGISTRATION).toString(); }
+    const QString type()         const { return getData().value(OPL::Db::TAILS_MAKE).toString(); } //TODO - Create String for make-model-variant
 };
 
 /*!
@@ -113,6 +113,9 @@ public:
     PilotEntry(const RowData_T &row_data);
     PilotEntry(int row_id, const RowData_T &row_data);
 
+    const QString lastName()  const { return getData().value(OPL::Db::PILOTS_LASTNAME).toString(); }
+    const QString firstName() const { return getData().value(OPL::Db::PILOTS_FIRSTNAME).toString(); }
+
 };
 
 /*!
@@ -157,6 +160,9 @@ public:
     AirportEntry();
     AirportEntry(const RowData_T &row_data);
     AirportEntry(int row_id, const RowData_T &row_data);
+
+    const QString iata() const { return getData().value(OPL::Db::AIRPORTS_IATA).toString(); }
+    const QString icao() const { return getData().value(OPL::Db::AIRPORTS_ICAO).toString(); }
 };
 
 } // namespace OPL

+ 1 - 1
src/gui/dialogues/firstrundialog.cpp

@@ -118,7 +118,7 @@ bool FirstRunDialog::finishSetup()
     writeSettings();
     QFileInfo database_file(OPL::Paths::databaseFileInfo());
 
-    if (database_file.exists()) {
+    if (database_file.exists() && database_file.size() != 0) {
 
         QMessageBox message_box(QMessageBox::Question, tr("Existing Database found"),
                                    tr("An existing database file has been detected on your system.<br>"

+ 28 - 28
src/gui/widgets/backupwidget.cpp

@@ -21,6 +21,7 @@
 #include "src/database/database.h"
 #include "src/functions/datetime.h"
 #include "src/database/dbsummary.h"
+#include "src/gui/dialogues/firstrundialog.h"
 
 #include <QListView>
 #include <QStandardItemModel>
@@ -62,7 +63,6 @@ void BackupWidget::refresh()
 
     // Get summary of each db file and populate lists (columns) of data
     for (const auto &entry : entries) {
-        DEB << "Filename string: " << entry;
         QMap<OPL::DbSummaryKey, QString> summary = OPL::DbSummary::databaseSummary(backup_dir.absoluteFilePath(entry));
         model->appendRow({new QStandardItem(summary[OPL::DbSummaryKey::total_time]),
                           new QStandardItem(summary[OPL::DbSummaryKey::total_flights]),
@@ -79,17 +79,17 @@ void BackupWidget::refresh()
 
 const QString BackupWidget::absoluteBackupPath()
 {
-    const QString backup_name = QLatin1String("logbook_backup_")
-            + OPL::DateTime::dateTimeToString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup)
-            + QLatin1String(".db");
+    const QString backup_name = backupName();
     return OPL::Paths::filePath(OPL::Paths::Backup, backup_name);
 }
 
 const QString BackupWidget::backupName()
 {
-    return  QLatin1String("logbook_backup_")
-            + OPL::DateTime::dateTimeToString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup)
-            + QLatin1String(".db");
+    auto owner = DB->getPilotEntry(1);
+    return  QLatin1String("logbook_backup_%1_%2.db").arg(
+                OPL::DateTime::dateTimeToString(QDateTime::currentDateTime(), OPL::DateTimeFormat::Backup),
+                owner.lastName()
+                );
 }
 
 void BackupWidget::on_tableView_clicked(const QModelIndex &index)
@@ -253,26 +253,26 @@ void BackupWidget::on_restoreExternalPushButton_clicked()
     }
 }
 
-void BackupWidget::on_aboutPushButton_clicked()
+/*!
+ * \brief BackupWidget::on_createNewLogbookPushButton_clicked Enables the user to reset the database
+ */
+void BackupWidget::on_createNewLogbookPushButton_clicked()
 {
-    TODO << "Implement settings and automatic backups";
-    QString text = tr(
-
-                      "<h3><center>About Backups</center></h3>"
-                      "<br>"
-                      "<p>By creating a backup, you create a copy of your logbook for safekeeping. This copy includes all your "
-                      "flights, pilots, aircraft and currencies. By creating a backup, you are creating a snapshot of your logbook to date. This backup can "
-                      "later be restored. OpenPilotLog offers two kinds of backups: Local and External Backups.<br><br>Local backups "
-                      "are automatically stored in a folder on this computer and will show up in the list below. They can easily be created by selecting <b>Create Local backup</b> and restored with "
-                      "<b>Restore Local Backup</b>.<br><br>"
-                      "When using <b>Create External Backup</b>, you will be asked where to save your backup file. This can be an external hard drive, USB stick, a cloud location or any other location of your choice. "
-                      "This functionality can also be used to sync your database across devices or to take it with you when you buy a new PC. You can then import your backup file by selecting "
-                      "it with <b>Restore external backup</b>.</p>"
-                      "<p>Frequent backups are recommended to prevent data loss or corruption. It is also recommended to keep a backup copy in a location physically seperated from your main "
-                      "computer to prevent data loss due to system failures.</p>"
-                      //todo "<p>By default, OpenPilotLog creates a weekly automatic backup. If you would like to change this behaviour, you can adjust it in the settings.</p>"
-                      "<br>"
-                      );
-    QMessageBox msg_box(QMessageBox::Information, "About backups", text, QMessageBox::Ok, this);
-    msg_box.exec();
+    QMessageBox confirm(this);
+    confirm.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+    confirm.setDefaultButton(QMessageBox::No);
+    confirm.setIcon(QMessageBox::Warning);
+    confirm.setWindowTitle(tr("Start new Logbook"));
+    confirm.setText(tr("By starting a new logbook, you reset and empty the database currently in use.<br><br>"
+                       "You will be asked if you want to keep a backup of your current database, but it is highly "
+                       "recommended to create an external backup before starting a new logbook.<br><br>"
+                       "Do you want to continue?"
+                       ));
+    if (confirm.exec() == QMessageBox::Yes) {
+        auto frd = new FirstRunDialog(this);
+        if(!frd->exec()) {
+            WARN(tr("Creating New Logbook has been unsuccessful or aborted."));
+        }
+    }
+
 }

+ 1 - 1
src/gui/widgets/backupwidget.h

@@ -87,7 +87,7 @@ private slots:
     /*!
      * \brief Opens a QMessageBox that outlines the different functions of the Backupwidget to the user.
      */
-    void on_aboutPushButton_clicked();
+    void on_createNewLogbookPushButton_clicked();
 
 private:
     Ui::BackupWidget *ui;

+ 2 - 2
src/gui/widgets/backupwidget.ui

@@ -22,9 +22,9 @@
     </widget>
    </item>
    <item row="3" column="2">
-    <widget class="QPushButton" name="aboutPushButton">
+    <widget class="QPushButton" name="createNewLogbookPushButton">
      <property name="text">
-      <string>About Backups</string>
+      <string>Create New Logbook</string>
      </property>
     </widget>
    </item>

+ 0 - 10
src/gui/widgets/homewidget.cpp

@@ -224,13 +224,3 @@ void HomeWidget::fillLimitations()
         setLabelColour(ui->FlightTimeCalYearDisplayLabel, Colour::Orange);
     }
 }
-
-const QString HomeWidget::userName()
-{
-    const auto statement = QStringLiteral("SELECT firstname FROM pilots WHERE ROWID=1");
-    const auto name = DB->customQuery(statement, 1);
-    if (!name.isEmpty())
-        return name.first().toString();
-
-    return QString();
-}

+ 1 - 1
src/gui/widgets/homewidget.h

@@ -96,7 +96,7 @@ private:
     /*!
      * \brief Retreives the users first name from the database.
      */
-    const QString userName();
+    const inline QString userName() { return DB->getPilotEntry(1).firstName(); }
 
 public slots:
     void refresh();

+ 23 - 0
src/gui/widgets/settingswidget.cpp

@@ -383,6 +383,29 @@ void SettingsWidget::on_aboutPushButton_clicked()
     message_box.exec();
 }
 
+void SettingsWidget::on_aboutBackupsPushButton_clicked()
+{
+    QString text = tr(
+
+                      "<h3><center>About Backups</center></h3>"
+                      "<br>"
+                      "<p>By creating a backup, you create a copy of your logbook for safekeeping. This copy includes all your "
+                      "flights, pilots, aircraft and currencies. By creating a backup, you are creating a snapshot of your logbook to date. This backup can "
+                      "later be restored. OpenPilotLog offers two kinds of backups: Local and External Backups.<br><br>Local backups "
+                      "are automatically stored in a folder on this computer and will show up in the list below. They can easily be created by selecting <b>Create Local backup</b> and restored with "
+                      "<b>Restore Local Backup</b>.<br><br>"
+                      "When using <b>Create External Backup</b>, you will be asked where to save your backup file. This can be an external hard drive, USB stick, a cloud location or any other location of your choice. "
+                      "This functionality can also be used to sync your database across devices or to take it with you when you buy a new PC. You can then import your backup file by selecting "
+                      "it with <b>Restore external backup</b>.</p>"
+                      "<p>Frequent backups are recommended to prevent data loss or corruption. It is also recommended to keep a backup copy in a location physically seperated from your main "
+                      "computer to prevent data loss due to system failures.</p>"
+                      //todo "<p>By default, OpenPilotLog creates a weekly automatic backup. If you would like to change this behaviour, you can adjust it in the settings.</p>"
+                      "<br>"
+                      );
+    QMessageBox msg_box(QMessageBox::Information, "About backups", text, QMessageBox::Ok, this);
+    msg_box.exec();
+}
+
 void SettingsWidget::on_styleComboBox_currentTextChanged(const QString& new_style_setting)
 {
     if (new_style_setting == QLatin1String("Dark-Palette")) {

+ 3 - 0
src/gui/widgets/settingswidget.h

@@ -53,6 +53,7 @@ public:
 private slots:
 
     void on_aboutPushButton_clicked();
+    void on_aboutBackupsPushButton_clicked();
     void on_acftSortComboBox_currentIndexChanged(int index);
     void on_prefixLineEdit_textChanged(const QString &arg1);
     void on_lastnameLineEdit_editingFinished();
@@ -90,6 +91,8 @@ private slots:
     void on_currCustom2LineEdit_editingFinished();
     void on_languageComboBox_activated(int arg1);
 
+
+
 private:
     Ui::SettingsWidget *ui;
 

+ 19 - 12
src/gui/widgets/settingswidget.ui

@@ -981,11 +981,18 @@
      </widget>
      <widget class="QWidget" name="tab">
       <attribute name="title">
-       <string>About</string>
+       <string>Help</string>
       </attribute>
       <layout class="QGridLayout" name="gridLayout_8">
-       <item row="0" column="0">
-        <spacer name="horizontalSpacer_7">
+       <item row="0" column="1">
+        <widget class="QPushButton" name="aboutPushButton">
+         <property name="text">
+          <string>About openPilotLog</string>
+         </property>
+        </widget>
+       </item>
+       <item row="0" column="2">
+        <spacer name="horizontalSpacer_8">
          <property name="orientation">
           <enum>Qt::Horizontal</enum>
          </property>
@@ -997,15 +1004,8 @@
          </property>
         </spacer>
        </item>
-       <item row="0" column="1">
-        <widget class="QPushButton" name="aboutPushButton">
-         <property name="text">
-          <string>About openPilotLog</string>
-         </property>
-        </widget>
-       </item>
-       <item row="0" column="2">
-        <spacer name="horizontalSpacer_8">
+       <item row="0" column="0">
+        <spacer name="horizontalSpacer_7">
          <property name="orientation">
           <enum>Qt::Horizontal</enum>
          </property>
@@ -1017,6 +1017,13 @@
          </property>
         </spacer>
        </item>
+       <item row="1" column="1">
+        <widget class="QPushButton" name="aboutBackupsPushButton">
+         <property name="text">
+          <string>About Backups</string>
+         </property>
+        </widget>
+       </item>
       </layout>
      </widget>
     </widget>

+ 13 - 4
src/opl.h

@@ -22,6 +22,19 @@
 #include <QMessageBox>
 #include <QComboBox>
 
+#define APPNAME QStringLiteral("openPilotLog")
+#define ORGNAME QStringLiteral("opl")
+#define ORGDOMAIN QStringLiteral("https://github.com/fiffty-50/openpilotlog")
+#define OPL_VERSION 0
+#define OPL_SUBVERSION 1
+
+#if OPL_VERSION < 1
+    #define OPL_VERSION_STRING QString(QString::number(OPL_VERSION) + "." + QString::number(OPL_SUBVERSION)) + "-alpha"
+#else
+    #define OPL_VERSION_STRING QString(QString::number(OPL_VERSION) + "." + QString::number(OPL_SUBVERSION))
+#endif
+
+
 /*!
  *  \brief A namespace to collect constants and enums used throughout the application.
  *
@@ -38,10 +51,6 @@
  */
 namespace OPL {
 
-#define OPL_VERSION 0
-#define OPL_SUBVERSION 1
-#define OPL_VERSION_STRING QString(QString::number(OPL_VERSION) + "." + QString::number(OPL_SUBVERSION))
-
 #if defined(__GNUC__) || defined(__clang__)
     #define FUNC_IDENT __PRETTY_FUNCTION__
 #elif defined(_MSC_VER)

+ 137 - 0
src/testing/randomgenerator.cpp

@@ -0,0 +1,137 @@
+#include "randomgenerator.h"
+#include "src/database/database.h"
+#include "src/functions/calc.h"
+#include "src/opl.h"
+#include "src/functions/time.h"
+
+namespace OPL {
+
+RandomGenerator::RandomGenerator(bool safe_mode) :
+    safeMode(safe_mode)
+{
+    m_numberOfAirports = DB->getLastEntry(OPL::DbTable::Airports);
+    m_numberOfTails = DB->getLastEntry(OPL::DbTable::Tails);
+    m_numberOfPilots = DB->getLastEntry(OPL::DbTable::Pilots);
+}
+
+const FlightEntry RandomGenerator::randomFlight()
+{
+    const QDateTime dept_dt = randomDateTime();
+    const QDateTime dest_dt = dept_dt.addSecs(QRandomGenerator::global()->bounded(900, 50000));
+
+    const QString doft = dept_dt.date().toString(Qt::ISODate);
+    int tofb = OPL::Time::toMinutes(dept_dt.time());
+    int tonb = OPL::Time::toMinutes(dest_dt.time());
+
+    int pic = randomPilot();
+    int acft = randomTail();
+
+    const QString dept = randomAirport();
+    const QString dest = randomAirport();
+
+    int tblk = OPL::Time::blockMinutes(dept_dt.time(), dest_dt.time());
+    int tNight = OPL::Calc::calculateNightTime(dept, dest, dept_dt, tblk, 6);
+
+    auto flt_data = OPL::RowData_T();
+    flt_data.insert(OPL::Db::FLIGHTS_DOFT, doft);
+    flt_data.insert(OPL::Db::FLIGHTS_DEPT, dept);
+    flt_data.insert(OPL::Db::FLIGHTS_DEST, dest);
+    flt_data.insert(OPL::Db::FLIGHTS_PIC, pic);
+    flt_data.insert(OPL::Db::FLIGHTS_ACFT, acft);
+    flt_data.insert(OPL::Db::FLIGHTS_TOFB, tofb);
+    flt_data.insert(OPL::Db::FLIGHTS_TONB, tonb);
+    flt_data.insert(OPL::Db::FLIGHTS_TBLK, tblk);
+
+    if (tNight > 0) flt_data.insert(OPL::Db::FLIGHTS_TNIGHT, tNight);
+
+    bool pf = randomBool(); // Pilot Flying
+
+    // Take-Off and Landing
+    if (pf) {
+        flt_data.insert(OPL::Db::FLIGHTS_PILOTFLYING, 1);
+        if (OPL::Calc::isNight(dept, dept_dt, 6))
+            flt_data.insert(OPL::Db::FLIGHTS_TONIGHT, 1);
+        else
+            flt_data.insert(OPL::Db::FLIGHTS_TODAY, 1);
+        if (OPL::Calc::isNight(dest, dest_dt, 6))
+            flt_data.insert(OPL::Db::FLIGHTS_LDGNIGHT, 1);
+        else
+            flt_data.insert(OPL::Db::FLIGHTS_LDGDAY, 1);
+    }
+
+    int function;
+    if (pic == 1) {
+        flt_data.insert(OPL::Db::FLIGHTS_TPIC, tblk);
+        flt_data.insert(OPL::Db::FLIGHTS_SECONDPILOT, randomPilot());
+    } else {
+        function = QRandomGenerator::global()->bounded(1,4);
+        flt_data.insert(OPL::Db::FLIGHTS_SECONDPILOT, 1);
+        flt_data.insert(m_function_times[function], tblk);
+    }
+
+    return OPL::FlightEntry(flt_data);
+}
+
+const QTime RandomGenerator::randomTime()
+{
+    int h = QRandomGenerator::global()->bounded(0, 23);
+    int m = QRandomGenerator::global()->bounded(0, 59);
+    return QTime(h,m);
+}
+
+const QDate RandomGenerator::randomDate()
+{
+    int year = QRandomGenerator::global()->bounded(2000, 2021);
+    int month = QRandomGenerator::global()->bounded(1,12);
+    int day = QRandomGenerator::global()->bounded(1, 28);
+    return QDate(year, month, day);
+}
+
+const QDateTime RandomGenerator::randomDateTime()
+{
+    int year = QRandomGenerator::global()->bounded(2000, 2021);
+    int month = QRandomGenerator::global()->bounded(1,12);
+    int day = QRandomGenerator::global()->bounded(1, 28);
+    int hour = QRandomGenerator::global()->bounded(0, 23);
+    int minute = QRandomGenerator::global()->bounded(0,59);
+
+    return QDateTime(QDate(year, month, day), QTime(hour, minute));
+}
+
+const QString RandomGenerator::randomAirport()
+{
+    return DB->getAirportEntry(QRandomGenerator::global()->bounded(1, m_numberOfAirports)).icao();
+}
+
+const int RandomGenerator::randomPilot()
+{
+    if (!safeMode)
+        return QRandomGenerator::global()->bounded(1, m_numberOfPilots);
+
+    // verify entry exists before returning
+    int pilot;
+    do {
+        pilot = QRandomGenerator::global()->bounded(1, m_numberOfPilots);
+    } while (!DB->exists(Row(OPL::DbTable::Pilots, pilot)));
+    return pilot;
+}
+
+const int RandomGenerator::randomTail()
+{
+    if (!safeMode)
+        return QRandomGenerator::global()->bounded(1, m_numberOfTails);
+
+    // verify entry exists before returning
+    int acft;
+    do {
+        acft = QRandomGenerator::global()->bounded(1, m_numberOfTails);
+    } while (!DB->exists(Row(DbTable::Tails, acft)));
+    return acft;
+}
+
+const bool RandomGenerator::randomBool()
+{
+    return arc4random() > (RAND_MAX / 2);
+}
+
+} // namespace OPL

+ 46 - 0
src/testing/randomgenerator.h

@@ -0,0 +1,46 @@
+#ifndef RANDOMGENERATOR_H
+#define RANDOMGENERATOR_H
+
+#include "src/database/row.h"
+namespace OPL {
+
+/*!
+ * \brief The RandomGenerator class generates random data for testing and debugging purposes.
+ * \details Using the randomFlight() method it is possible to generate a random flight with
+ * pilot and tail details already present in the database. For this to work, there cannot be any
+ * gaps in the database, i.e. the row_id must be rising uninterruptedly. If this cannot be guaranteed,
+ * use pass safe_mode = true as an argument when creating instantiating the generator.
+ */
+class RandomGenerator
+{
+public:
+    RandomGenerator(bool safe_mode = false);
+
+    const FlightEntry randomFlight();
+
+    const QTime randomTime();
+    const QDate randomDate();
+    const QDateTime randomDateTime();
+    const QString randomAirport();
+    const int randomPilot();
+    const int randomTail();
+    const bool randomBool();
+
+
+private:
+    bool safeMode = false;
+    const static inline QStringList m_function_times = {
+        OPL::Db::FLIGHTS_TPIC,
+        OPL::Db::FLIGHTS_TPICUS,
+        OPL::Db::FLIGHTS_TSIC,
+        OPL::Db::FLIGHTS_TDUAL,
+        OPL::Db::FLIGHTS_TFI,
+    };
+
+    int m_numberOfPilots;
+    int m_numberOfAirports;
+    int m_numberOfTails;
+};
+
+} // namespace OPL
+#endif // RANDOMGENERATOR_H