Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IOF XML import & some CSV imports & some support for Eventor for QE3 #962

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
742d07a
Add IOF XML import, 2 CSV imports (prototype)
arnost00 Dec 30, 2023
d54dfaa
Add flag to event config - we need to know what type of data we have …
arnost00 Jul 12, 2023
2d811ad
Txt Imports - extended handling of starttime
arnost00 Jul 12, 2023
7dae307
Add raceNumber to EventConfig, add support for raceNumber to XML expo…
arnost00 Jul 18, 2023
a919377
Code cleanup (names, enums)
arnost00 Jul 19, 2023
f9d9432
Code update - use static_cast
arnost00 Jul 25, 2023
b431bed
TxtImport - fix for format "h:mm:ss", XmlImporter - fix exception whe…
arnost00 Jul 25, 2023
4838ffc
XmlImporter code cleanup, use std::optional
arnost00 Jul 28, 2023
24607aa
XmlImporter - add import of relays (Eventor), and Event (Eventor).
arnost00 Jul 31, 2023
c74042f
IOF XML 3.0 single race results export compatible with Eventor, typo fix
arnost00 Aug 2, 2023
85854d0
Fix IOF XML 3.0 single race results export compatible with Eventor.
arnost00 Aug 2, 2023
23ff29d
Unite QE Id used in XML export <Id type="QuickEvent">
arnost00 Aug 2, 2023
51b3de0
Fix IOF XML 3.0 relay race results export compatible with Eventor.
arnost00 Aug 2, 2023
235b644
Fix relay results - summary run status of relay
arnost00 Aug 2, 2023
91860cc
CSV export of startlist for TV Graphics - single race
arnost00 Aug 3, 2023
95843bf
XmlImporter code cleanup
arnost00 Aug 3, 2023
6f23662
Competitors Widget - add button for quick switch first & last name.
arnost00 Aug 9, 2023
d24768a
CSV Result export - add DNS, add single file results call to Runs->Ex…
arnost00 Aug 10, 2023
6d01345
WMOC - prepare for more information columns in startlist & results
arnost00 Aug 10, 2023
97a012d
Emma service update (txt part) for new Emma Racom client (support fo…
arnost00 Aug 12, 2023
e74029f
Emma service update (txt part) for new Emma Racom client (support fo…
arnost00 Aug 12, 2023
c6e2b49
Emma service update (txt part) for new Emma Racom client (new CSV st…
arnost00 Aug 14, 2023
0569d9e
Fix IOF XML 3.0 relay race results export compatible with Eventor & b…
arnost00 Aug 17, 2023
8c188a9
CardReader - Show Bib (can use Bib in find), DISQ is readOnly, Can us…
arnost00 Aug 17, 2023
8f402cd
fix: export of invalid time in oresults service
otahirs Aug 18, 2023
99a739f
In the card reader plugin, RunFlagDialog is used instead of two chec…
arnost00 Aug 22, 2023
f748e1d
Fix receipt for free order - correct split times are shown. Not all c…
arnost00 Aug 23, 2023
045780e
CSV Result export - fix for Cze races & for older races without prope…
arnost00 Aug 23, 2023
45813a7
CSV imports - some fixes : UI, better SI handling, import with key is…
arnost00 Aug 29, 2023
fef392f
Fix Emma client CSV startlist export - set missing UTF-8 codec
arnost00 Sep 18, 2023
4634630
ReportOptionsDialog - fixed init bugs in Class Start Selection groupbox
arnost00 Sep 18, 2023
276dbc2
Fix bugs reported from 6. kolo PLŽ - Podhorní Újezd a Vojice [2023-0…
arnost00 Sep 19, 2023
7553556
Fix for Qt6 build
arnost00 Jan 1, 2024
e48c432
Add UI item and code to select start number in ReportOptionsDialog fo…
arnost00 Jul 26, 2023
7f2bd3b
Fix stageId for fill class list (selected start number)
arnost00 Jul 26, 2023
c411cb8
ReportOptionsDialog - fixed init bugs in Class Start Selection groupbox
arnost00 Sep 18, 2023
9e7b170
Convert and fix report option dialog to qe3 branch
arnost00 Jul 28, 2023
cf74430
Fix code build after rebase
arnost00 Mar 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ namespace quickevent {
namespace core {
namespace exporters {

StageResultsCsvExporter::StageResultsCsvExporter(QObject *parent)
: Super(parent)
StageResultsCsvExporter::StageResultsCsvExporter(bool is_iof_race, QObject *parent)
: Super(parent),
m_isIofRace(is_iof_race)
{
}

Expand Down Expand Up @@ -52,7 +53,13 @@ void StageResultsCsvExporter::exportClasses(bool single_file)
csv_dir.mkpath(sub_dir);

if (single_file) {
QFile f_csv(csv_dir.absolutePath() + '/' + sub_dir + '/' + "results.csv");
QString file_name = outFile();
if (file_name.isEmpty())
file_name = "results.csv";
QString path = csv_dir.absolutePath() +'/';
if (!simplePath())
path += sub_dir + '/';
QFile f_csv(path + file_name);
qfInfo() << "Generating:" << f_csv.fileName();
if (!f_csv.open(QFile::WriteOnly))
qfError() << "Cannot open file" << f_csv.fileName() + "for writing.";
Expand Down Expand Up @@ -102,17 +109,18 @@ void StageResultsCsvExporter::exportClass(int class_id, QTextStream &csv)
QString qs = qb.toString();
qs.replace("{{stage_id}}", QString::number(currentStage()));
qs.replace("{{class_id}}", QString::number(class_id));
QString with_dns = (withDidNotStart()) ? "" : " AND runs.finishTimeMs>0";
qf::core::sql::Query q = execSql(qs);
if(q.next()) {
QString class_name = q.value("classes.name").toString();
qf::core::sql::QueryBuilder qb2;
qb2.select2("competitors", "registration, lastName, firstName, country, club")
qb2.select2("competitors", "registration, lastName, firstName, country, club, iofId, startNumber, licence")
.select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName")
.select2("runs", "*")
.select2("clubs","name, abbr")
.from("competitors")
.join("LEFT JOIN clubs ON substr(competitors.registration, 1, 3) = clubs.abbr")
.joinRestricted("competitors.id", "runs.competitorId", "runs.stageId={{stage_id}} AND runs.isRunning AND runs.finishTimeMs>0", "JOIN")
.joinRestricted("competitors.id", "runs.competitorId", "runs.stageId={{stage_id}} AND runs.isRunning"+with_dns, "JOIN")
.where("competitors.classId={{class_id}}")
.orderBy("runs.notCompeting, runs.disqualified, runs.timeMs");
QString qs2 = qb2.toString();
Expand All @@ -124,11 +132,12 @@ void StageResultsCsvExporter::exportClass(int class_id, QTextStream &csv)
int prev_time_ms = 0;
QString spos; // keep last number when same time
while(q2.next()) {
pos++;
auto run_status = quickevent::core::RunStatus::fromQuery(q2);
int time_ms = q2.value(QStringLiteral("timeMs")).toInt();
QString stime = og::TimeMs(time_ms).toString('.');
if(run_status.isOk()) {
bool is_finish = q2.value(QStringLiteral("finishTimeMs")).toInt() > 0;
if(run_status.isOk() && is_finish) {
pos++;
if(time_ms != prev_time_ms)
spos = QString::number(pos);
}
Expand All @@ -143,25 +152,62 @@ void StageResultsCsvExporter::exportClass(int class_id, QTextStream &csv)
if (club.isEmpty())
club = q2.value("competitors.registration").toString().left(3);
}

if (m_isIofRace)
csv << q2.value("competitors.iofId").toString() << m_separator;
else
csv << q2.value("competitors.registration").toString() << m_separator;
csv << q2.value("competitors.startNumber").toString() << m_separator;
csv << class_name << m_separator;
csv << spos << m_separator;
csv << q2.value("competitorName").toString() << m_separator;
csv << club << m_separator;
csv << q2.value("competitors.country").toString() << m_separator;
if (m_isIofRace) {
QString country_abbr;
qf::core::sql::QueryBuilder qb3;
qb3.select2("clubs","name, abbr")
.from("competitors")
.join("LEFT JOIN clubs ON competitors.country = clubs.name");
qf::core::sql::Query q3 = execSql(qb3.toString());
if(q3.next())
country_abbr = q2.value("clubs.abbr").toString();

csv << q2.value("competitors.country").toString() << m_separator;
csv << country_abbr << m_separator;
}
else {
csv << q2.value("competitors.licence").toString() << m_separator;
csv << q2.value("competitors.iofId").toString() << m_separator;
csv << q2.value("competitors.registration").toString().left(3) << m_separator;
}
csv << stime << m_separator;
csv << run_status.toHtmlExportString();
QString rs = run_status.toHtmlExportString();
csv << ((rs == "OK" && !is_finish) ? "ERR" : rs); // older races without proper run flags
csv << Qt::endl;
}
}
}

void StageResultsCsvExporter::exportCsvHeader(QTextStream &csv)
{
if (m_isIofRace)
csv << "IofId" << m_separator;
else
csv << "Reg" << m_separator;
csv << "Bib" << m_separator;
csv << "Class" << m_separator;
csv << "Position" << m_separator;
csv << "Name" << m_separator;
csv << "Club" << m_separator;
csv << "Country" << m_separator;
if (m_isIofRace) {
csv << "Country" << m_separator;
csv << "CountryAbbr" << m_separator;
}
else {
csv << "Lic" << m_separator;
csv << "IofId" << m_separator;
csv << "ClubAbbr" << m_separator;
}
csv << "Time" << m_separator;
csv << "Status";
csv << Qt::endl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ class QUICKEVENTCORE_DECL_EXPORT StageResultsCsvExporter : public FileExporter

using Super = FileExporter;
public:
StageResultsCsvExporter(QObject *parent = nullptr);
QF_PROPERTY_IMPL(QString, o, O, utFile)
QF_PROPERTY_IMPL(bool, s, S, implePath)
QF_PROPERTY_IMPL(bool, w, W, ithDidNotStart)
public:
StageResultsCsvExporter(bool is_iof_race = false, QObject *parent = nullptr);
void generateCsvMulti();
void generateCsvSingle();
void setSeparator(QChar sep) { m_separator = sep; }
Expand All @@ -25,6 +29,7 @@ class QUICKEVENTCORE_DECL_EXPORT StageResultsCsvExporter : public FileExporter
void exportCsvHeader(QTextStream &csv);
private:
QChar m_separator = ';';
bool m_isIofRace = false;
};

}}}
Expand Down
1 change: 1 addition & 0 deletions quickevent/app/quickevent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ add_executable(quickevent
plugins/Oris/src/orisimporter.cpp
plugins/Oris/src/orisplugin.cpp
plugins/Oris/src/txtimporter.cpp
plugins/Oris/src/xmlimporter.cpp
plugins/Receipts/src/receiptsplugin.cpp
plugins/Receipts/src/receiptsprinter.cpp
#plugins/Receipts/src/receiptsprinteroptions.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ quickevent::core::si::CheckedCard CardCheckerFreeOrderCpp::checkCard(const quick
}

error_mis_punch = !map_of_control_codes.isEmpty();
checked_punches = map_of_control_codes.values();
checked_card.setMisPunch(error_mis_punch);

quickevent::core::si::CheckedPunch finish_punch;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <plugins/Event/src/eventplugin.h>
#include <plugins/Runs/src/findrunnerwidget.h>
#include <plugins/Competitors/src/competitorsplugin.h>
#include <plugins/Runs/src/runflagsdialog.h>

#include <QSettings>
#include <QFile>
Expand Down Expand Up @@ -86,11 +87,11 @@ class Model : public quickevent::core::og::SqlTableModel
col_classes_name,
col_competitorName,
col_competitors_registration,
col_competirors_bib,
col_runs_startTimeMs,
col_runs_timeMs,
col_runs_finishTimeMs,
col_runs_misPunch,
col_runs_disqualified,
col_runFlags,
col_runs_cardLent,
col_runs_cardReturned,
col_cards_checkTime,
Expand All @@ -102,7 +103,11 @@ class Model : public quickevent::core::og::SqlTableModel
public:
explicit Model(QObject *parent);

int columnCount(const QModelIndex &) const override { return col_COUNT; }
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;

using Super::value;
QVariant value(int row_ix, int column_ix) const Q_DECL_OVERRIDE;
};

Model::Model(QObject *parent)
Expand All @@ -114,12 +119,12 @@ Model::Model(QObject *parent)
setColumn(col_classes_name, ColumnDefinition("classes.name", tr("Class")));
setColumn(col_competitorName, ColumnDefinition("competitorName", tr("Name")));
setColumn(col_competitors_registration, ColumnDefinition("competitors.registration", tr("Reg")));
setColumn(col_competirors_bib, ColumnDefinition("competitors.startNumber", tr("Bib")));
setColumn(col_runs_startTimeMs, ColumnDefinition("runs.startTimeMs", tr("Start")).setCastType(qMetaTypeId<quickevent::core::og::TimeMs>()).setReadOnly(true));
setColumn(col_runs_timeMs, ColumnDefinition("runs.timeMs", tr("Time")).setCastType(qMetaTypeId<quickevent::core::og::TimeMs>()).setReadOnly(true));
setColumn(col_runs_finishTimeMs, ColumnDefinition("runs.finishTimeMs", tr("Finish")).setCastType(qMetaTypeId<quickevent::core::og::TimeMs>()).setReadOnly(true));
setColumn(col_runs_misPunch, ColumnDefinition("runs.misPunch", tr("Error")).setToolTip(tr("Card mispunch")).setReadOnly(true));
setColumn(col_runs_disqualified, ColumnDefinition("runs.disqualified", tr("DISQ")).setToolTip(tr("Disqualified")));
setColumn(col_runs_cardLent, ColumnDefinition("cardLent", tr("RT")).setToolTip(tr("Card in rent table")).setReadOnly(true).setCastType(QMetaType::Bool));
setColumn(col_runFlags, ColumnDefinition("runFlags", tr("Run flags")).setReadOnly(true));
setColumn(col_runs_cardLent, ColumnDefinition("cardLent", tr("RT")).setToolTip(tr("Card in rent table")).setReadOnly(true).setCastType(QVariant::Bool));
setColumn(col_runs_cardReturned, ColumnDefinition("runs.cardReturned", tr("R")).setToolTip(tr("Card returned")));
setColumn(col_cards_checkTime, ColumnDefinition("cards.checkTime", tr("CTIME")).setToolTip(tr("Card check time")).setReadOnly(true));
setColumn(col_cards_startTime, ColumnDefinition("cards.startTime", tr("STIME")).setToolTip(tr("Card start time")).setReadOnly(true));
Expand Down Expand Up @@ -160,6 +165,45 @@ QVariant Model::data(const QModelIndex &index, int role) const
}
return Super::data(index, role);
}


QVariant Model::value(int row_ix, int column_ix) const
{
if(column_ix == col_runFlags) {
qf::core::utils::TableRow row = tableRow(row_ix);
bool is_disqualified = row.value(QStringLiteral("runs.disqualified")).toBool();
bool mis_punch = row.value(QStringLiteral("runs.misPunch")).toBool();
bool bad_check = row.value(QStringLiteral("runs.badCheck")).toBool();
bool not_start = row.value(QStringLiteral("runs.notStart")).toBool();
bool not_finish = row.value(QStringLiteral("runs.notFinish")).toBool();
bool is_disqualified_by_organizer = row.value(QStringLiteral("runs.disqualifiedByOrganizer")).toBool();
bool over_time = row.value(QStringLiteral("runs.overTime")).toBool();
bool not_competing = row.value(QStringLiteral("runs.notCompeting")).toBool();
QStringList sl;
if(not_competing)
sl << tr("NC", "NotCompeting");
if(mis_punch)
sl << tr("MP", "MisPunch");
if(bad_check)
sl << tr("BC", "BadCheck");
if(not_start)
sl << tr("DNS", "DidNotStart");
if(not_finish)
sl << tr("DNF", "DidNotFinish");
if(is_disqualified_by_organizer)
sl << tr("DO", "disqualifiedByOrganizer");
if(over_time)
sl << tr("OT", "OverTime");
if(is_disqualified && !mis_punch && !bad_check && !not_start && !not_finish && !is_disqualified_by_organizer && !over_time)
sl << tr("DSQ", "Disqualified");
if(sl.isEmpty())
return QStringLiteral("");
else
return sl.join(',');
}
return Super::value(row_ix, column_ix);
}

}

CardReaderWidget::CardReaderWidget(QWidget *parent)
Expand Down Expand Up @@ -205,6 +249,17 @@ CardReaderWidget::CardReaderWidget(QWidget *parent)
}
ui->tblCards->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->tblCards, &qfw::TableView::customContextMenuRequested, this, &CardReaderWidget::onCustomContextMenuRequest);

connect(ui->tblCards, &qfw::TableView::editCellRequest, this, [this](QModelIndex index) {
auto col = index.column();
if(col == Model::col_runFlags) {
Runs::RunFlagsDialog dlg(this);
dlg.load(m_cardsModel, ui->tblCards->toTableModelRowNo(ui->tblCards->currentIndex().row()));
if(dlg.exec()) {
dlg.save();
}
}
}, Qt::QueuedConnection);
}

CardReaderWidget::~CardReaderWidget()
Expand Down Expand Up @@ -407,11 +462,12 @@ void CardReaderWidget::reload()
int current_stage = getPlugin<CardReaderPlugin>()->currentStageId();
qfs::QueryBuilder qb;
qb.select2("cards", "id, siId, runId, checkTime, startTime, finishTime, runIdAssignError")
.select2("runs", "id, startTimeMs, timeMs, finishTimeMs, misPunch, disqualified, cardReturned")
.select2("competitors", "registration")
.select2("runs", "id, startTimeMs, timeMs, finishTimeMs, misPunch, disqualified, badCheck, notStart, notFinish, disqualifiedByOrganizer, overTime, notCompeting, cardReturned")
.select2("competitors", "registration, startNumber")
.select2("classes", "name")
.select("COALESCE(lastName, '') || ' ' || COALESCE(firstName, '') AS competitorName")
.select("lentcards.siid IS NOT NULL OR runs.cardLent AS cardLent")
.select("'' AS runFlags")
.from("cards")
.joinRestricted("cards.siId", "lentcards.siid", "NOT lentcards.ignored")
.join("cards.runId", "runs.id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ namespace Ui {
class CardReaderWidget;
}

namespace quickevent::core::og { class SqlTableModel; }

namespace qf {
namespace core { namespace model { class SqlTableModel; } }
namespace qmlwidgets {
class Action;
namespace framework { class PartWidget; class Plugin; }
Expand Down Expand Up @@ -108,7 +109,7 @@ private slots:
private:
Ui::CardReaderWidget *ui;
qf::qmlwidgets::Action *m_actAssignCard = nullptr;
qf::core::model::SqlTableModel *m_cardsModel = nullptr;
quickevent::core::og::SqlTableModel *m_cardsModel = nullptr;
quickevent::gui::audio::Player *m_audioPlayer = nullptr;
siut::DeviceDriver *f_siDriver = nullptr;
siut::CommPort *m_commPort = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ CompetitorWidget::CompetitorWidget(QWidget *parent) :
}

connect(ui->edFind, &FindRegistrationEdit::registrationSelected, this, &CompetitorWidget::onRegistrationSelected);
connect(ui->btnSwitchNames, &QPushButton::clicked, this, &CompetitorWidget::onSwitchNames);

dataController()->setDocument(new Competitors::CompetitorDocument(this));
m_runsModel = new CompetitorRunsModel(this);
Expand Down Expand Up @@ -424,4 +425,12 @@ bool CompetitorWidget::saveData()
return false;
}

void CompetitorWidget::onSwitchNames()
{
auto *doc = dataController()->document();
QString fn = doc->value("firstname").toString();
QString ln = doc->value("lastname").toString();
doc->setValue("firstname",ln);
doc->setValue("lastname",fn);
}

Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class CompetitorWidget : public qf::qmlwidgets::framework::DataDialogWidget

private slots:
void onRegistrationSelected(const QVariantMap &values);
void onSwitchNames();
private:
Q_SLOT bool loadRunsTable();
Q_SLOT bool saveRunsTable();
Expand Down
Loading
Loading