Esempio n. 1
0
void EventPlugin::onDbEvent(const QString &name, QSqlDriver::NotificationSource source, const QVariant &payload)
{
	qfLogFuncFrame() << "name:" << name << "source:" << source << "payload:" << payload;
	if(name == QLatin1String(DBEVENT_NOTIFY_NAME)) {
		if(source == QSqlDriver::OtherSource) {
			QJsonDocument jsd = QJsonDocument::fromJson(payload.toString().toUtf8());
			QVariantMap m = jsd.toVariant().toMap();
			QString domain = m.value(QStringLiteral("domain")).toString();
			if(domain.isEmpty()) {
				qfWarning() << "DbNotify with invalid domain, payload:" << payload.toString();
				return;
			}
			QString event_name = m.value(QStringLiteral("event")).toString();
			if(event_name.isEmpty()) {
				qfWarning() << "DbNotify with invalid event name, payload:" << payload.toString();
				return;
			}
			if(event_name == eventName()) {
				QVariant pl = m.value(QStringLiteral("payload"));
				qfDebug() << "emitting domain:" << domain << "payload:" << pl;
				emit dbEventNotify(domain, pl);
			}
		}
		else {
			//qfDebug() << "self db notify";
		}
	}
}
Esempio n. 2
0
void RacomClient::onRawSIDataUdpSocketReadyRead()
{
	if(status() != Status::Running)
		return;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
	QUdpSocket *sock = rawDataUdpSocket();
	QNetworkDatagram dg = sock->receiveDatagram();
	QByteArray data = dg.data();
	qfInfo() << data.toHex();
	// remove possible initial garbage
	int i = 0;
	for(i=0; i<data.size(); i++)
		if(data.at(i) == 0x02)
			break;
	data = data.mid(i);
	// remove possible multiple 0x02
	for(i=1; i<data.size(); i++)
		if(data.at(i) != 0x02)
			break;
	data = data.mid(i-1);
	qfInfo() << "stripped data:" << data.toHex();
	CardReader::CardReaderPlugin *plugin = cardReaderPlugin();
	if(plugin) {
		if(!m_siDriver) {
			m_siDriver = new siut::DeviceDriver(this);
			connect(m_siDriver, &siut::DeviceDriver::siTaskFinished, plugin, &CardReader::CardReaderPlugin::emitSiTaskFinished);
		}
		m_siDriver->processData(data);
	}
#else
	qfWarning() << "Racom client is not supported with Qt < 5.8";
#endif
}
Esempio n. 3
0
int main(int argc, char *argv[])
{
	int ret = 0;

	QCoreApplication::setOrganizationDomain("quickbox.org");
	QCoreApplication::setOrganizationName("QuickBox");
	QCoreApplication::setApplicationName("qsqlmon");

	qf::core::LogDevice::setDefinedCategories(QStringList() << "TimeScope");
	qf::core::LogDevice::setGlobalTresholds(argc, argv);
	QScopedPointer<qf::core::LogDevice> file_log_device(qf::core::FileLogDevice::install());

	qfError() << "qfError() test OK.";
	qfWarning() << "qfWarning() test OK.";
	qfInfo() << "qfInfo() test OK.";
	qfDebug() << "qfDebug() test OK.";

	//QLocale::setDefault(QLocale(QLocale::Czech, QLocale::CzechRepublic));
	//QLocale::setDefault(QLocale::system());
	/// defaultni locales jsou z LC_ALL
	qfInfo() << "Default locale set to:" << QLocale().name();

	TheApp app(argc, argv);

	MainWindow main_window;
	main_window.show();
	ret = app.exec();

	qfDebug() << "bye ...";
	return ret;
}
Esempio n. 4
0
int MessageBoxSingleton::critical(QWidget *parent, const QString &text)
{
	if(parent == nullptr) {
		parent = QApplication::activeWindow();
	}
	qfWarning() << text;
	return QMessageBox::critical(parent, trUtf8("Error"), text);
}
Esempio n. 5
0
void EventPlugin::initEventConfig()
{
	if(m_eventConfig == nullptr) {
		m_eventConfig = new Event::EventConfig(this);
	}
	else {
		qfWarning() << "Event config exists already!";
	}
}
Esempio n. 6
0
QObject *CompetitorsPlugin::createCompetitorDocument(QObject *parent)
{
	CompetitorDocument *ret = new CompetitorDocument(parent);
	if(!parent) {
		qfWarning() << "Parent is NULL, created class will have QQmlEngine::JavaScriptOwnership.";
		qmlEngine()->setObjectOwnership(ret, QQmlEngine::JavaScriptOwnership);
	}
	return ret;
}
Esempio n. 7
0
bool ResultsExporter::exportResults()
{
	ResultsExporterSettings ss = settings();
	if(!QDir().mkpath(ss.exportDir())) {
		qfError() << "Cannot create export dir:" << ss.exportDir();
		return false;
	}
	qfInfo() << "ResultsExporter export dir:" << ss.exportDir();
	if(ss.outputFormat() == static_cast<int>(ResultsExporterSettings::OutputFormat::CSOS)) {
		int current_stage = eventPlugin()->currentStageId();
		QString fn = ss.exportDir() + "/results-csos.txt";
		runsPlugin()->exportResultsCsosStage(current_stage, fn);
		return true;
	}
	if(ss.outputFormat() == static_cast<int>(ResultsExporterSettings::OutputFormat::IofXml3)) {
		int current_stage = eventPlugin()->currentStageId();
		QString fn = ss.exportDir() + "/results-csos.txt";
		runsPlugin()->exportResultsIofXml30Stage(current_stage, fn);
		return true;
	}
	else if(ss.outputFormat() == static_cast<int>(ResultsExporterSettings::OutputFormat::HtmlMulti)) {
		quickevent::core::exporters::StageResultsHtmlExporter exp;
		exp.setOutDir(ss.exportDir());
		exp.generateHtml();

		QString cmd = ss.whenFinishedRunCmd();
		if(!cmd.isEmpty()) {
			qfInfo() << "Starting process:" << cmd;
			QProcess *proc = new QProcess();
			connect(proc, &QProcess::readyReadStandardOutput, [proc]() {
				QByteArray ba = proc->readAllStandardOutput();
				qfInfo().noquote() << "PROC stdout:" << ba;
			});
			connect(proc, &QProcess::readyReadStandardError, [proc]() {
				QByteArray ba = proc->readAllStandardError();
				qfWarning().noquote() << "PROC stderr:" << ba;
			});
			connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [proc](int exit_code, QProcess::ExitStatus exit_status) {
				if(exit_status == QProcess::ExitStatus::CrashExit)
					qfError() << "PROC crashed";
				else
					qfInfo() << "PROC finished with exit code:" << exit_code;
				proc->deleteLater();
			});

			proc->start(cmd);
		}
		return true;
	}
	qfError() << "Unsupported output format:" << ss.outputFormat();
	return false;
}
Esempio n. 8
0
void ClassesWidget::reload()
{
	if(eventPlugin()->eventName().isEmpty()) {
		m_classesModel->clearRows();
		m_courseCodesModel->clearRows();
		return;
	}
	int stage_id = selectedStageId();
	{
		qf::core::sql::QueryBuilder qb1;
		qb1.select("COUNT(*)")
				.from("runs")
				.join("runs.competitorId", "competitors.id")
				.where("competitors.classId=classdefs.classId")
				.where("NOT runs.offRace")
				.where("runs.stageId=" QF_IARG(stage_id));
		qfs::QueryBuilder qb;
		qb.select2("classes", "*")
				.select2("classdefs", "*")
				.select2("courses", "id, name, length, climb")
				.select("(" + qb1.toString() + ") AS runsCount")
				.from("classes")
				.joinRestricted("classes.id", "classdefs.classId", "classdefs.stageId=" QF_IARG(stage_id))
				.join("classdefs.courseId", "courses.id")
				.orderBy("classes.name");//.limit(10);
		/*
		int class_id = m_cbxClasses->currentData().toInt();
		if(class_id > 0) {
			qb.where("competitors.classId=" + QString::number(class_id));
		}
		*/
		m_classesModel->setQueryBuilder(qb);
		m_classesModel->reload();
	}
	{
		qf::core::sql::Query q(m_classesModel->sqlConnection());
		q.exec("SELECT COUNT(*) FROM classdefs WHERE stageId=" QF_IARG(stage_id));
		bool ro = true;
		if(q.next())
			ro = (q.value(0).toInt() == 0);
		if(ro) {
			qfWarning() << tr("Courses are not imported, class table is read only.");
		}
		ui->tblClasses->setReadOnly(ro);
	}
	reloadCourseCodes();
}
Esempio n. 9
0
int main(int argc, char* argv[])
{
	QScopedPointer<qf::core::LogDevice> file_log_device(qf::core::FileLogDevice::install());
	file_log_device->setDomainTresholds(argc, argv);
	file_log_device->setPrettyDomain(true);

	qfError() << QThread::currentThread() << "QFLog(ERROR) test OK.";
	qfWarning() << "QFLog(WARNING) test OK.";
	qfInfo() << "QFLog(INFO) test OK.";
	qfDebug() << "QFLog(DEBUG) test OK.";

	TheApp app(argc, argv);
	QCoreApplication::setOrganizationName("OrienteeringTools");
	QCoreApplication::setOrganizationDomain("sourceforge.net");
	QCoreApplication::setApplicationName("QSiCli");

	QQmlEngine engine;
	#ifdef Q_OS_UNIX
	engine.addImportPath(QCoreApplication::applicationDirPath() + "/../lib/qml");
	#else
	engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
	#endif
	engine.rootContext()->setContextProperty("TheApp", &app);
	QUrl extensions_url = QUrl::fromLocalFile(QCoreApplication::applicationDirPath() + "/divers/qsicli/extensions/qml/init.qml");
	qfDebug() << "creating extensions on path:" << extensions_url.toString();
	QQmlComponent component(&engine, extensions_url);
	if(!component.isReady()) {
		qfError() << component.errorString();
	}
	else {
		QObject *extensions_root = qobject_cast<QWidget*>(component.create());
		qfDebug() << "extensions created" << extensions_root;
	}

	MainWindow w;
	//qDebug() << "showing main window";
	w.show();
	//qDebug() << "enterring the message loop";
	int ret = app.exec();
	qfInfo() << "bye ...";
	return ret;
}
Esempio n. 10
0
quickevent::core::si::CheckedCard CardCheckerClassicCpp::checkCard(const quickevent::core::si::ReadCard &read_card)
{
	qfDebug() << "read card:" << read_card.toString();

	int run_id = read_card.runId();
	QVariantMap course;
	if(run_id > 0)
		course = courseCodesForRunId(run_id);

	quickevent::core::si::CheckedCard checked_card;
	if(!course.isEmpty())
		return checked_card;

	checked_card.setCourseId(course.value(QStringLiteral("id")).toInt());
	checked_card.setRunId(course.value(QStringLiteral("runId")).toInt());
	//checked_card.setPunches();
	//Log.info("course:", JSON.stringify(read_card, null, 2));
	int stage_id = stageIdForRun(run_id);

	bool error_mis_punch = false;
	QList<quickevent::core::si::CheckedPunch> checked_punches;
	QVariantList course_codes = course.value(QStringLiteral("codes")).toList();
	QList<quickevent::core::si::ReadPunch> read_punches = read_card.punchList();

	//........... normalize times .....................
	// checked card times are in msec relative to run start time
	// startTime, checkTime and finishTime in in msec relative to event start time 00
	int start00sec = stageStartSec(stage_id);
	checked_card.setStageStartTimeMs(start00sec * 1000);
	//checked_card.setCheckTimeMs = null;
	//checked_card.startTimeMs = null;
	if(read_card.checkTime() != 0xEEEE) {
		checked_card.setCheckTimeMs(msecIntervalAM(start00sec * 1000, read_card.checkTime() * 1000));
	}
	//var start_time_sec = null;
	if(read_card.startTime() == 0xEEEE) {        //take start record from start list
		if(run_id > 0) {
			checked_card.setStartTimeMs(startTimeSec(run_id) * 1000);
			//console.warn(start_time_sec);
		}
		bool is_debug = false;
		if(is_debug && checked_card.checkTimeMs() > 0) {
			// take start from check if zero, for testing only
			checked_card.setStartTimeMs((checked_card.checkTimeMs() / 60000 + 1) * 60000);
			qfWarning() << "Taking start time from check for debugging purposes only, start time:" << (checked_card.startTimeMs() / 60000);
		}
	}
	else {
		checked_card.setStartTimeMs(msecIntervalAM(start00sec * 1000, read_card.startTime() * 1000));
	}

	//checked_card.finishTimeMs = null;
	if(read_card.finishTime() == 0xEEEE) {
		error_mis_punch = true;
	}
	else {
		checked_card.setFinishTimeMs(msecIntervalAM(start00sec * 1000, read_card.finishTime() * 1000));
		if(read_card.finishTimeMs())
			checked_card.setFinishTimeMs(checked_card.finishTimeMs() + read_card.finishTimeMs());
	}

	int read_punch_check_ix = 0;
	for(int j=0; j<course_codes.length(); j++) {
		QVariantMap course_code = course_codes[j].toMap();
		quickevent::core::si::CheckedPunch checked_punch;
		checked_punch.setCode(course_code.value(QStringLiteral("code")).toInt());
		checked_punches << checked_punch;
		int k;
		for(k=read_punch_check_ix; k<read_punches.length(); k++) { //scan card
			const quickevent::core::si::ReadPunch &read_punch = read_punches[k];
			int code = course_code.value(QStringLiteral("code")).toInt();
			int alt_code = course_code.value(QStringLiteral("altcode")).toInt();
			qfDebug() << j << k << "looking for:" << checked_punch.code() << "on card:" << read_punch.code() << "vs. code:" << code << "alt:" << alt_code;
			//console.info("code:", JSON.stringify(course_code, null, 2));
			if(read_punch.code() == code || read_punch.code() == alt_code) {
				int read_punch_time_ms = read_punch.time() * 1000;
				if(read_punch.msec())
					read_punch_time_ms += read_punch.msec();
				checked_punch.setStpTimeMs(msecIntervalAM(checked_card.stageStartTimeMs() + checked_card.startTimeMs(), read_punch_time_ms));
				qfDebug() << j << "OK";
				break;
			}
		}
		if(k == read_punches.length()) {
			// code not found
			qfDebug() << j << "NOT FOUND";
			bool code_ooo = course_code.value(QStringLiteral("outoforder")).toBool();
			if(!code_ooo) // for postgres, Query.values() should return lower case keys
				error_mis_punch = true;
		}
		else {
			read_punch_check_ix = k + 1;
		}
	}
	checked_card.setMisPunch(error_mis_punch);

	quickevent::core::si::CheckedPunch finish_punch;
	finish_punch.setCode(quickevent::core::si::PunchRecord::FINISH_PUNCH_CODE);
	finish_punch.setStpTimeMs(msecIntervalAM(checked_card.startTimeMs(), checked_card.finishTimeMs()));
	checked_punches << finish_punch;

	int prev_stp_time_ms = 0;
	for(int k=0; k<checked_punches.length(); k++) {
		quickevent::core::si::CheckedPunch &checked_punch = checked_punches[k];
		if(checked_punch.stpTimeMs()) {
			if(prev_stp_time_ms > 0)
				checked_punch.setLapTimeMs(checked_punch.stpTimeMs() - prev_stp_time_ms);
			prev_stp_time_ms = checked_punch.stpTimeMs();
		}
		else {
			prev_stp_time_ms = 0;
		}
	}

	qfDebug() << "check result:" << checked_card.toString();
	return checked_card;

}
Esempio n. 11
0
void ClassesWidget::import_ocad_v8()
{
	QString fn = qfd::FileDialog::getOpenFileName(this, tr("Open file"));
	if(fn.isEmpty())
		return;
	QFile f(fn);
	if(f.open(QFile::ReadOnly)) {
		QStringList lines;
		while (true) {
			QByteArray ba = f.readLine();
			if(ba.isEmpty())
				break;
			lines << QString::fromUtf8(ba).trimmed();
		}
		try {
			QMap<QString, CourseDef> defined_courses_map;
			for(QString line : lines) {
				// [classname];coursename;0;lenght_km;climb;S1;dist_1;code_1[;dist_n;code_n];dist_finish;F1
				if(line.isEmpty())
					continue;
				QStringList class_names;
				qfc::String course_name = normalize_course_name(line.section(';', 1, 1));
				QString class_name = line.section(';', 0, 0);
				if(class_name.isEmpty()) {
					for(auto ch : {'-', ',', ':', '+'}) {
						if(course_name.contains(ch)) {
							class_names = course_name.splitAndTrim(ch);
							break;
						}
					}
					if(class_names.isEmpty() && !course_name.isEmpty())
						class_names << course_name;
				}
				else {
					class_names << class_name;
				}
				if(class_names.isEmpty()) {
					//class_names << course_name;
					qfWarning() << "cannot deduce class name, skipping line:" << line;
					continue;
				}
				if(defined_courses_map.contains(course_name)) {
					CourseDef cd = defined_courses_map.value(course_name);
					QStringList classes = cd.classes() << class_names;
					defined_courses_map[course_name].setClasses(classes);
					continue;
				}
				CourseDef &cd = defined_courses_map[course_name];
				cd.setName(course_name);
				cd.setClasses(class_names);
				{
					QString s = line.section(';', 3, 3).trimmed();
					s.replace('.', QString()).replace(',', QString());
					cd.setLenght(s.toInt());
				}
				{
					QString s = line.section(';', 4, 4).trimmed();
					s.replace('.', QString()).replace(',', QString());
					cd.setClimb(s.toInt());
				}
				{
					qfc::String s = line.section(';', 6);
					QVariantList codes;
					QStringList sl = s.splitAndTrim(';');
					for (int i = 0; i < sl.count()-2; i+=2) {
						bool ok;
						int code = sl[i+1].toInt(&ok);
						if(ok)
							codes << code;
						else
							QF_EXCEPTION(QString("Invalid code definition '%1' at sequence no: %2 in '%3'\nline: %4").arg(sl[i+1]).arg(i).arg(s).arg(line));
					}
					cd.setCodes(codes);
				}
			}
			importCourses(defined_courses_map.values());
		}
		catch (const qf::core::Exception &e) {
			qf::qmlwidgets::framework::MainWindow *fwk = qf::qmlwidgets::framework::MainWindow::frameWork();
			qf::qmlwidgets::dialogs::MessageBox::showException(fwk, e);
		}
	}
}
Esempio n. 12
0
QVariantMap ReceiptsPlugin::receiptTablesData(int card_id)
{
	qfLogFuncFrame() << card_id;
	QF_TIME_SCOPE("receiptTablesData()");
	QVariantMap ret;
	CardReader::ReadCard read_card = cardReaderPlugin()->readCard(card_id);
	CardReader::CheckedCard checked_card = cardReaderPlugin()->checkCard(read_card);
	int current_stage_id = eventPlugin()->currentStageId();
	int run_id = checked_card.runId();
	int course_id = checked_card.courseId();
	int current_standings = 0;
	int competitors_finished = 0;
	QMap<int, int> best_laps; //< position->time
	///QMap<int, int> missing_codes; //< pos->code
	///QSet<int> out_of_order_codes;
	{
		qf::core::model::SqlTableModel model;
		qf::core::sql::QueryBuilder qb;
		qb.select2("competitors", "*")
				.select2("runs", "*")
				.select2("classes", "name")
				.select("COALESCE(competitors.lastName, '') || ' ' || COALESCE(competitors.firstName, '') AS competitorName")
				.from("runs")
				.join("runs.competitorId", "competitors.id")
				.join("competitors.classId", "classes.id")
				.where("runs.id=" QF_IARG(run_id));
		model.setQuery(qb.toString());
		model.reload();
		if(model.rowCount() == 1) {
			int class_id = model.value(0, "competitors.classId").toInt();
			{
				// find best laps for competitors class
				qf::core::sql::QueryBuilder qb_minlaps;
				// TODO: remove position field from DB in 0.1.5
				qb_minlaps.select("runlaps.position, MIN(runlaps.lapTimeMs) AS minLapTimeMs")
						.from("competitors")
						.joinRestricted("competitors.id", "runs.competitorId", "runs.stageId=" QF_IARG(current_stage_id) " AND competitors.classId=" QF_IARG(class_id), "JOIN")
						.joinRestricted("runs.id", "runlaps.runId", "runlaps.position > 0 AND runlaps.lapTimeMs > 0", "JOIN")
						.groupBy("runlaps.position");
				QString qs = qb_minlaps.toString();
				//qfInfo() << qs;
				qf::core::sql::Query q;
				q.exec(qs);
				while(q.next()) {
					int position = q.value("position").toInt();
					if(position == 0) {
						qfWarning() << "position == 0 in best runlaps";
						continue;
					}
					int lap = q.value("minLapTimeMs").toInt();
					if(lap == 0) {
						qfWarning() << "minLapTimeMs == 0 in best runlaps";
						continue;
					}
					best_laps[position] = lap;
					//qfInfo() << "bestlaps[" << pos << "] =" << lap;
				}
			}
			if(checked_card.isOk()) {
				// find current standings
				qf::core::sql::QueryBuilder qb;
				qb.select2("runs", "timeMs")
						.select("runs.disqualified OR NOT runs.isRunning OR runs.isRunning IS NULL OR runs.misPunch AS dis")
						.from("competitors")
						.joinRestricted("competitors.id", "runs.competitorId", "runs.stageId=" QF_IARG(current_stage_id) " AND competitors.classId=" QF_IARG(class_id))
						.where("runs.finishTimeMs > 0")
						.orderBy("misPunch, disqualified, isRunning, runs.timeMs");
				//qfInfo() << qb.toString();
				qf::core::sql::Query q;
				q.exec(qb.toString(), qf::core::Exception::Throw);
				while (q.next()) {
					bool dis = q.value("dis").toBool();
					int time = q.value("timeMs").toInt();
					if(!dis) {
						if(time <= checked_card.timeMs())
							current_standings++;
					}
					competitors_finished++;
				}
			}
		}
		qfu::TreeTable tt = model.toTreeTable();
		{
			qf::core::sql::QueryBuilder qb;
			qb.select2("courses", "length, climb")
					.select("(SELECT COUNT(*) FROM coursecodes WHERE courseId=courses.id) AS controlCount")
					.from("courses")
					.where("courses.id=" QF_IARG(course_id));
			qf::core::sql::Query q;
			q.exec(qb.toString());
			if(q.next()) {
				QSqlRecord rec = q.record();
				for (int i = 0; i < rec.count(); ++i) {
					QString fld_name = rec.fieldName(i);
					tt.setValue(fld_name, rec.value(i));
				}
			}
		}
		{
			qf::core::sql::QueryBuilder qb;
			qb.select2("config", "ckey, cvalue, ctype")
					.from("config")
					.where("ckey LIKE 'event.%'");
			qf::core::sql::Query q;
			q.exec(qb.toString());
			while(q.next()) {
				QVariant v = qf::core::Utils::retypeStringValue(q.value("cvalue").toString(), q.value("ctype").toString());
				tt.setValue(q.value("ckey").toString(), v);
			}
		}
		tt.setValue("stageCount", eventPlugin()->stageCount());
		tt.setValue("currentStageId", eventPlugin()->currentStageId());
		qfDebug() << "competitor:\n" << tt.toString();
		ret["competitor"] = tt.toVariant();
	}
	{
		qfu::TreeTable tt;
		tt.appendColumn("position", QVariant::Int);
		tt.appendColumn("code", QVariant::Int);
		tt.appendColumn("stpTimeMs", QVariant::Int);
		tt.appendColumn("lapTimeMs", QVariant::Int);
		tt.appendColumn("lossMs", QVariant::Int);
 		QMapIterator<QString, QVariant> it(checked_card);
		while(it.hasNext()) {
			it.next();
			if(it.key() != QLatin1String("punches"))
				tt.setValue(it.key(), it.value());
		}
		tt.setValue("isOk", checked_card.isOk());
		int position = 0;
		for(auto v : checked_card.punches()) {
			CardReader::CheckedPunch punch(v.toMap());
			qfu::TreeTableRow ttr = tt.appendRow();
			++position;
			int code = punch.code();
			ttr.setValue("position", position);
			ttr.setValue("code", code);
			ttr.setValue("stpTimeMs", punch.stpTimeMs());
			int lap = punch.lapTimeMs();
			ttr.setValue("lapTimeMs", lap);
			int best_lap = best_laps.value(position);
			if(lap > 0 && best_lap > 0) {
				int loss = lap - best_lap;
				ttr.setValue("lossMs", loss);
			}
		}
		/*
		{
			// runlaps table contains also finish time entry, it is under FINISH_PUNCH_POS
			// currently best_laps[999] contains best finish lap time for this class
			int loss = 0;
			int best_lap = best_laps.value(CardReader::CardReaderPlugin::FINISH_PUNCH_POS);
			if(best_lap > 0)
				loss = checked_card.finishLapTimeMs() - best_lap;
			//qfInfo() << "control_count:" << control_count << "finishLapTimeMs:" << checked_card.finishLapTimeMs() << "- best_lap:" << best_lap << "=" << loss;
			tt.setValue("finishLossMs", loss);
		}
		*/
		{
			QSet<int> correct_codes;
			for (int i = 0; i < checked_card.punchCount(); ++i) {
				correct_codes << checked_card.punchAt(i).code();
			}
			QVariantList xc;
			for (int i = 0; i < read_card.punchCount(); ++i) {
				int code = read_card.punchAt(i).code();
				if(!correct_codes.contains(code)) {
					xc.insert(xc.count(), QVariantList() << (i+1) << code);
				}
			}
			tt.setValue("extraCodes", xc);
		}
		tt.setValue("currentStandings", current_standings);
		tt.setValue("competitorsFinished", competitors_finished);
		tt.setValue("timeMs", checked_card.timeMs());

		qfDebug() << "card:\n" << tt.toString();
		ret["card"] = tt.toVariant();
	}
	return ret;
}
Esempio n. 13
0
static QString copy_sql_table(const QString &table_name, const QSqlRecord &dest_rec, qfs::Connection &from_conn, qfs::Connection &to_conn)
{
	qfLogFuncFrame() << table_name;
	qfInfo() << "Copying table:" << table_name;
	if(!to_conn.tableExists(table_name)) {
		qfWarning() << "Destination table" << table_name << "doesn't exist!";
		return QString();
	}
	qfs::Query from_q(from_conn);
	if(!from_q.exec(QString("SELECT * FROM %1").arg(table_name))) {
		qfWarning() << "Source table" << table_name << "doesn't exist!";
		return QString();
	}
	const QSqlRecord src_rec = from_q.record();
	// copy only fields which can be found in both records
	QSqlRecord rec;
	for (int i = 0; i < dest_rec.count(); ++i) {
		QString fld_name = dest_rec.fieldName(i);
		if(src_rec.indexOf(fld_name) >= 0) {
			qfDebug() << fld_name << "\t added to imported fields since it is present in both databases";
			rec.append(dest_rec.field(i));
		}
	}
	auto *sqldrv = to_conn.driver();
	QString qs = sqldrv->sqlStatement(QSqlDriver::InsertStatement, table_name, rec, true);
	qfDebug() << qs;
	qfs::Query to_q(to_conn);
	if(!to_q.prepare(qs)) {
		return QString("Cannot prepare insert table SQL statement, table: %1.").arg(table_name);
	}
	bool has_id_int = false;
	while(from_q.next()) {
		if(table_name == QLatin1String("config")) {
			if(from_q.value(0).toString() == QLatin1String("db.version"))
				continue;
		}
		for (int i = 0; i < rec.count(); ++i) {
			QSqlField fld = rec.field(i);
			QString fld_name = fld.name();
			//qfDebug() << "copy:" << fld_name << from_q.value(fld_name);
			QVariant v = from_q.value(fld_name);
			v.convert(rec.field(i).type());
			if(!has_id_int
					&& (fld.type() == QVariant::Int
						|| fld.type() == QVariant::UInt
						|| fld.type() == QVariant::LongLong
						|| fld.type() == QVariant::ULongLong)
					&& fld_name == QLatin1String("id")) {
				// probably ID INT AUTO_INCREMENT
				//max_id = qMax(max_id, v.toInt());
				has_id_int = true;
			}
			to_q.addBindValue(v);
		}
		if(!to_q.exec())
			return QString("SQL Error: %1").arg(to_q.lastError().text());
	}
	if(has_id_int && to_conn.driverName().endsWith(QLatin1String("PSQL"), Qt::CaseInsensitive)) {
		// set sequence current value when importing to PSQL
		qfInfo() << "updating seq number table:" << table_name;
		if(!to_q.exec("SELECT pg_catalog.setval(pg_get_serial_sequence(" QF_SARG(table_name) ", 'id'), MAX(id)) FROM " QF_CARG(table_name), !qf::core::Exception::Throw)) {
			return QString("Cannot update sequence counter, table: %1.").arg(table_name);
		}
	}
	return QString();
}
Esempio n. 14
0
void RacomClientSirxdConnection::onReadyRead()
{
	m_data += m_socket->readAll();
	while (true) {
		int ix = m_data.indexOf('\n');
		if(ix < 0)
			break;
		QByteArray rec = m_data.mid(0, ix).trimmed();
		m_data = m_data.mid(ix + 1);
		static const QByteArray READOUT("Readout;");
		static const QByteArray SPLIT("Split;");
		if(rec.startsWith(READOUT)) {
			enum {
				ColCardNumber = 1,
				ColCheckTime = 2,
				ColStartTime = 4,
				ColFinishTime = 6,
				ColPunchCount = 8,
			};
			QList<QByteArray> splits = rec.split(';');
			siut::SICard card;
			card.setCardNumber(splits.value(ColCardNumber).toInt());
			int secs, msecs;
			parse_time(splits.value(ColCheckTime), secs, msecs);
			card.setCheckTime(secs);
			parse_time(splits.value(ColStartTime), secs, msecs);
			card.setStartTime(secs);
			parse_time(splits.value(ColFinishTime), secs, msecs);
			card.setFinishTime(secs);
			card.setFinishTimeMs(msecs);
			int punch_cnt = splits.value(ColPunchCount).toInt();
			QVariantList punches;
			for (int i = 0; i < punch_cnt; ++i) {
				siut::SIPunch punch;
				punch.setCode(splits.value(ColPunchCount + 1 + 3*i + 0).toInt());
				parse_time(splits.value(ColPunchCount + 1 + 3*i + 1), secs, msecs);
				punch.setTime(secs);
				punch.setMsec(msecs);
				punches << punch;
			}
			card.setPunches(punches);
			CardReader::CardReaderPlugin *plugin = cardReaderPlugin();
			plugin->emitSiTaskFinished((int)siut::SiTask::Type::CardRead, card);
		}
		else if(rec.startsWith(SPLIT)) {
			enum {
				ColCardNumber = 1,
				ColCode = 2,
				ColTime = 3,
			};
			QList<QByteArray> splits = rec.split(';');
			siut::SIPunch punch;
			punch.setCardNumber(splits.value(ColCardNumber).toInt());
			punch.setCode(splits.value(ColCode).toInt());
			int secs, msecs;
			parse_time(splits.value(ColTime), secs, msecs);
			punch.setTime(secs);
			punch.setMsec(msecs);
			CardReader::CardReaderPlugin *plugin = cardReaderPlugin();
			plugin->emitSiTaskFinished((int)siut::SiTask::Type::Punch, punch);
		}
		else {
			qfWarning() << "Throwing away unrecognised sirxd message:" << QString::fromUtf8(rec);
		}
	}
}
Esempio n. 15
0
/*
static Receipts::ReceiptsPlugin *receiptsPlugin()
{
	qff::MainWindow *fwk = qff::MainWindow::frameWork();
	auto *ret = qobject_cast<Receipts::ReceiptsPlugin *>(fwk->plugin("Receipts"));
	QF_ASSERT(ret != nullptr, "Bad plugin", return 0);
	return ret;
}
*/
void ReceiptsPrinter::printReceipt(const QString &report_file_name, const QVariantMap &report_data)
{
	qfLogFuncFrame();
	QF_TIME_SCOPE("ReceiptsPrinter::printReceipt()");
	const ReceiptsPrinterOptions &printer_opts = m_printerOptions;
	QPrinter *printer = nullptr;
	QPaintDevice *paint_device = nullptr;
	if(printer_opts.printerType() == (int)ReceiptsPrinterOptions::PrinterType::GraphicPrinter) {
		QF_TIME_SCOPE("init graphics printer");
		QPrinterInfo pi = QPrinterInfo::printerInfo(printer_opts.graphicsPrinterName());
		if(pi.isNull()) {
			for(auto s : QPrinterInfo::availablePrinterNames()) {
				qfInfo() << "available printer:" << s;
			}
			pi = QPrinterInfo::defaultPrinter();
		}
		if(pi.isNull()) {
			qfWarning() << "Default printer not set";
			return;
		}
		qfInfo() << "printing on:" << pi.printerName();
		printer = new QPrinter(pi);
		paint_device = printer;
	}
	else {
		qfInfo() << "printing on:" << printer_opts.characterPrinterModel() << "at:" << printer_opts.characterPrinterDevice();
		qff::MainWindow *fwk = qff::MainWindow::frameWork();
		paint_device = fwk;
	}
	qf::qmlwidgets::reports::ReportProcessor rp(paint_device);
	{
		QF_TIME_SCOPE("setting report and data");
		rp.setReport(report_file_name);
		for(auto key : report_data.keys()) {
			rp.setTableData(key, report_data.value(key));
		}
	}
	if(printer_opts.printerType() == (int)ReceiptsPrinterOptions::PrinterType::GraphicPrinter) {
		QF_TIME_SCOPE("process graphics");
		{
			QF_TIME_SCOPE("process report");
			rp.process();
		}
		qf::qmlwidgets::reports::ReportItemMetaPaintReport *doc;
		{
			QF_TIME_SCOPE("getting processor output");
			doc = rp.processorOutput();
		}
		qf::qmlwidgets::reports::ReportItemMetaPaint *it = doc->child(0);
		if(it) {
			QF_TIME_SCOPE("draw meta-paint");
			qf::qmlwidgets::reports::ReportPainter painter(paint_device);
			painter.drawMetaPaint(it);
		}
		QF_SAFE_DELETE(printer);
	}
	else if(printer_opts.printerType() == (int)ReceiptsPrinterOptions::PrinterType::CharacterPrinter) {
		QDomDocument doc;
		doc.setContent(QLatin1String("<?xml version=\"1.0\"?><report><body/></report>"));
		QDomElement el_body = doc.documentElement().firstChildElement("body");
		qf::qmlwidgets::reports::ReportProcessor::HtmlExportOptions opts;
		opts.setConvertBandsToTables(false);
		rp.processHtml(el_body, opts);
		//qfInfo() << doc.toString();
		QList<QByteArray> data_lines = createPrinterData(el_body, printer_opts);
		auto save_file = [data_lines](const QString &fn) {
			QFile f(fn);
			if(f.open(QFile::WriteOnly)) {
				for(QByteArray ba : data_lines) {
					f.write(ba);
					f.write("\n");
				}
			}
			else {
				qfError() << "Cannot open file" << f.fileName() << "for writing!";
			}
		};
		if(!printer_opts.characterPrinterDirectory().isEmpty()) {
			QString fn = printer_opts.characterPrinterDirectory();
			qf::core::utils::FileUtils::ensurePath(fn);
			QCryptographicHash ch(QCryptographicHash::Sha1);
			for(QByteArray ba : data_lines)
				ch.addData(ba);
			fn += '/' + QString::fromLatin1(ch.result().toHex().mid(0, 8)) + ".txt";
			save_file(fn);
		}
		else if (!printer_opts.characterPrinterDevice().isEmpty()) {
			save_file(printer_opts.characterPrinterDevice());
		}
	}
}