2
0

statistics.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /*
  2. *openPilotLog - A FOSS Pilot Logbook Application
  3. *Copyright (C) 2020-2023 Felix Turowsky
  4. *
  5. *This program is free software: you can redistribute it and/or modify
  6. *it under the terms of the GNU General Public License as published by
  7. *the Free Software Foundation, either version 3 of the License, or
  8. *(at your option) any later version.
  9. *
  10. *This program is distributed in the hope that it will be useful,
  11. *but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. *GNU General Public License for more details.
  14. *
  15. *You should have received a copy of the GNU General Public License
  16. *along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #include "statistics.h"
  19. #include "src/database/database.h"
  20. /*!
  21. * \brief OPL::Statistics::totalTime Looks up Total Blocktime in the flights database
  22. * \param TimeFrame - The timeframe used for the calculations.
  23. * \return Amount of Total Block Time in minutes
  24. */
  25. int OPL::Statistics::totalTime(TimeFrame time_frame)
  26. {
  27. QString statement;
  28. QDate start;
  29. QString start_date;
  30. switch (time_frame) {
  31. case TimeFrame::AllTime:
  32. statement = QStringLiteral("SELECT SUM(tblk) FROM flights");
  33. break;
  34. case TimeFrame::CalendarYear:
  35. start.setDate(QDate::currentDate().year(), 1, 1);
  36. start_date = start.toString(Qt::ISODate);
  37. start_date.append(QLatin1Char('\''));
  38. start_date.prepend(QLatin1Char('\''));
  39. statement = QLatin1String("SELECT SUM(tblk) FROM flights WHERE doft >= ") + start_date;
  40. break;
  41. case TimeFrame::Rolling12Months:
  42. start = QDate::fromJulianDay(QDate::currentDate().toJulianDay() - 365);
  43. start_date = start.toString(Qt::ISODate);
  44. start_date.append(QLatin1Char('\''));
  45. start_date.prepend(QLatin1Char('\''));
  46. statement = QLatin1String("SELECT SUM(tblk) FROM flights WHERE doft >= ") + start_date;
  47. break;
  48. case TimeFrame::Rolling28Days:
  49. start = QDate::fromJulianDay(QDate::currentDate().toJulianDay() - 28);
  50. start_date = start.toString(Qt::ISODate);
  51. start_date.append(QLatin1Char('\''));
  52. start_date.prepend(QLatin1Char('\''));
  53. statement = QLatin1String("SELECT SUM(tblk) FROM flights WHERE doft >= ") + start_date;
  54. break;
  55. }
  56. auto db_return = DB->customQuery(statement, 1);
  57. if (!db_return.isEmpty())
  58. return db_return.first().toInt();
  59. return 0;
  60. }
  61. /*!
  62. * \brief OPL::Statistics::currencyTakeOffLanding Returns the amount of Take Offs and
  63. * Landings performed in the last x days. If no vallue for days is provided, 90 is used,
  64. * as per EASA regulations
  65. * \return QVector<QString>{#TO,#LDG}
  66. */
  67. QVector<QVariant> OPL::Statistics::countTakeOffLanding(int days)
  68. {
  69. QDate start = QDate::fromJulianDay(QDate::currentDate().toJulianDay() - days);
  70. QString startdate = start.toString(Qt::ISODate);
  71. startdate.append(QLatin1Char('\''));
  72. startdate.prepend(QLatin1Char('\''));
  73. QString statement = QLatin1String("SELECT "
  74. " SUM(IFNULL(flights.toDay,0) + IFNULL(flights.toNight,0)) AS 'TO', "
  75. " SUM(IFNULL(flights.ldgDay,0) + IFNULL(flights.ldgNight,0)) AS 'LDG' "
  76. " FROM flights "
  77. " WHERE doft >=") + startdate;
  78. QVector<QVariant> result = DB->customQuery(statement, 2);
  79. // make sure a value is returned instead of NULL
  80. for (const auto &var : result) {
  81. if (var.isNull())
  82. result.replace(result.indexOf(var), 0);
  83. }
  84. return result;
  85. }
  86. QVector<QPair<QString, QString>> OPL::Statistics::totals()
  87. {
  88. QString statement = QStringLiteral("SELECT "
  89. "printf('%02d',CAST(SUM(tblk) AS INT)/60)||':'||printf('%02d',CAST(SUM(tblk) AS INT)%60) AS 'TOTAL', "
  90. "printf('%02d',CAST(SUM(tSPSE) AS INT)/60)||':'||printf('%02d',CAST(SUM(tSPSE) AS INT)%60) AS 'SP SE', "
  91. "printf('%02d',CAST(SUM(tSPME) AS INT)/60)||':'||printf('%02d',CAST(SUM(tSPME) AS INT)%60) AS 'SP ME', "
  92. "printf('%02d',CAST(SUM(tNIGHT) AS INT)/60)||':'||printf('%02d',CAST(SUM(tNIGHT) AS INT)%60) AS 'NIGHT', "
  93. "printf('%02d',CAST(SUM(tIFR) AS INT)/60)||':'||printf('%02d',CAST(SUM(tIFR) AS INT)%60) AS 'IFR', "
  94. "printf('%02d',CAST(SUM(tPIC) AS INT)/60)||':'||printf('%02d',CAST(SUM(tPIC) AS INT)%60) AS 'PIC', "
  95. "printf('%02d',CAST(SUM(tPICUS) AS INT)/60)||':'||printf('%02d',CAST(SUM(tPICUS) AS INT)%60) AS 'PICUS', "
  96. "printf('%02d',CAST(SUM(tSIC) AS INT)/60)||':'||printf('%02d',CAST(SUM(tSIC) AS INT)%60) AS 'SIC', "
  97. "printf('%02d',CAST(SUM(tDual) AS INT)/60)||':'||printf('%02d',CAST(SUM(tDual) AS INT)%60) AS 'DUAL', "
  98. "printf('%02d',CAST(SUM(tFI) AS INT)/60)||':'||printf('%02d',CAST(SUM(tFI) AS INT)%60) AS 'INSTRUCTOR', "
  99. "printf('%02d',CAST(SUM(tSIM) AS INT)/60)||':'||printf('%02d',CAST(SUM(tSIM) AS INT)%60) AS 'SIMULATOR', "
  100. "printf('%02d',CAST(SUM(tMP) AS INT)/60)||':'||printf('%02d',CAST(SUM(tMP) AS INT)%60) AS 'MultPilot', "
  101. "CAST(SUM(toDay) AS INT) AS 'TO Day', CAST(SUM(toNight) AS INT) AS 'TO Night', "
  102. "CAST(SUM(ldgDay) AS INT) AS 'LDG Day', CAST(SUM(ldgNight) AS INT) AS 'LDG Night' "
  103. "FROM flights");
  104. QVector<QString> columns = {QLatin1String("total"), QLatin1String("spse"), QLatin1String("spme"),
  105. QLatin1String("night"), QLatin1String("ifr"), QLatin1String("pic"),
  106. QLatin1String("picus"), QLatin1String("sic"), QLatin1String("dual"),
  107. QLatin1String("fi"), QLatin1String("sim"), QLatin1String("multipilot"),
  108. QLatin1String("today"), QLatin1String("tonight"), QLatin1String("ldgday"),
  109. QLatin1String("ldgnight")
  110. };
  111. QSqlQuery query(statement);
  112. QVector<QPair<QString, QString>> output;
  113. QString value;
  114. query.next();
  115. for (const auto &column : columns) {
  116. value = query.value(columns.indexOf(column)).toString();
  117. if (!value.isEmpty()) {
  118. output.append(QPair<QString, QString>{column, value});
  119. } else {
  120. output.append(QPair<QString, QString>{column, QLatin1String("00:00")});
  121. }
  122. }
  123. return output;
  124. }
  125. /*!
  126. * \brief Calculates the date of expiry for the take-off and landing currency.
  127. *
  128. * The default value for days is 90.
  129. * \return
  130. */
  131. QDate OPL::Statistics::currencyTakeOffLandingExpiry(int expiration_days)
  132. {
  133. int number_of_days = 0;
  134. QVector<QVariant> takeoff_landings;
  135. // Check if enough take-offs and landings exist within the expiration period, if that's not the case
  136. // we are out of currency and we can stop right there.
  137. takeoff_landings = countTakeOffLanding(expiration_days);
  138. if (takeoff_landings[0].toInt() < 3 || takeoff_landings[1].toInt() < 3)
  139. return QDate::currentDate();
  140. // Go back in time to find a point at which number of Take-Offs and Landings >= 3
  141. for (int i=0; i <= expiration_days; i++) {
  142. takeoff_landings = countTakeOffLanding(i);
  143. //DEB << takeoff_landings;
  144. if (takeoff_landings[0].toInt() >= 3 && takeoff_landings[1].toInt() >= 3) {
  145. number_of_days = i;
  146. //DEB << "Loop position i =" << i;
  147. break;
  148. }
  149. }
  150. // The expiration date of currency is now currentDate - number of days + expiration_days (default 90)
  151. QDate expiration_date = QDate::fromJulianDay(QDate::currentDate().toJulianDay() - number_of_days);
  152. //DEB << expiration_date.addDays(expiration_days);
  153. return expiration_date.addDays(expiration_days);;
  154. }