コード例 #1
0
ファイル: receiptsplugin.cpp プロジェクト: arnost00/quickbox
bool ReceiptsPlugin::printReceipt(int card_id)
{
	QF_TIME_SCOPE("ReceiptsPlugin::printReceipt()");
	try {
		printReceipt_classic(card_id);
		return true;
	}
	catch(const qf::core::Exception &e) {
		qfError() << e.toString();
	}
	return false;
}
コード例 #2
0
ファイル: receiptsplugin.cpp プロジェクト: arnost00/quickbox
bool ReceiptsPlugin::printCard(int card_id)
{
	qfLogFuncFrame() << "card id:" << card_id;
	QF_TIME_SCOPE("ReceiptsPlugin::printCard()");
	try {
		QVariantMap dt = readCardTablesData(card_id);
		receiptsPrinter()->printReceipt(manifest()->homeDir() + "/reports/sicard.qml", dt);
		return true;
	}
	catch(const qf::core::Exception &e) {
		qfError() << e.toString();
	}
	return false;
}
コード例 #3
0
ファイル: receiptsplugin.cpp プロジェクト: arnost00/quickbox
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;
}
コード例 #4
0
ファイル: receiptsprinter.cpp プロジェクト: mezkov/quickbox
/*
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());
		}
	}
}