KItinerary

elbticket.cpp
1/*
2 SPDX-FileCopyrightText: 2023 Volker Krause <vkrause@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "elbticket.h"
7
8#include <QDebug>
9
10using namespace KItinerary;
11
12ELBTicket::~ELBTicket() = default;
13
14ELBTicketSegment ELBTicket::segment1() const
15{
16 ELBTicketSegment segment;
17 segment.m_ticket = *this;
18 segment.m_offset = 49;
19 return segment;
20}
21
22ELBTicketSegment ELBTicket::segment2() const
23{
24 ELBTicketSegment segment;
25 segment.m_ticket = *this;
26 segment.m_offset = 85;
27 return segment.isValid() ? segment : ELBTicketSegment{};
28}
29
30static QDate dateFromDayCount(int year, int day, const QDateTime &contextDate)
31{
32 const auto y = contextDate.date().year() - contextDate.date().year() % 10 + year;
33 const auto d = QDate(y, 1, 1).addDays(day - 1);
34 if (y > contextDate.date().year()) {
35 return QDate(y - 10, 1, 1).addDays(day - 1);
36 }
37 return d;
38}
39
40QDate ELBTicket::emissionDate(const QDateTime &contextDate) const
41{
42 return dateFromDayCount(year(), emissionDay(), contextDate);
43}
44
45QDate ELBTicket::validFromDate(const QDateTime &contextDate) const
46{
47 return dateFromDayCount(beginValidityDay() < emissionDay() ? year() + 1 : year(), beginValidityDay(), contextDate);
48}
49
50QDate ELBTicket::validUntilDate(const QDateTime &contextDate) const
51{
52 auto y = year();
53 if (beginValidityDay() < emissionDay()) {
54 ++y;
55 }
56 if (endValidityDay() < beginValidityDay()) {
57 ++y;
58 }
59 return dateFromDayCount(y, endValidityDay(), contextDate);
60}
61
62QString ELBTicket::rawData() const
63{
64 return QString::fromUtf8(m_data);
65}
66
67QString ELBTicket::readString(int start, int len) const
68{
69 if (m_data.size() <= start + len) {
70 return {};
71 }
72
73 return QString::fromUtf8(m_data.constData() + start, len);
74}
75
76int ELBTicket::readNumber(int start, int len) const
77{
78 if (m_data.size() <= start + len) {
79 return -1;
80 }
81
82 return QByteArrayView(m_data.constData() + start, len).toInt();
83}
84
85bool ELBTicket::maybeELBTicket(const QByteArray &data)
86{
87 return data.size() >= 85 && data[0] == 'e';
88}
89
90std::optional<ELBTicket> ELBTicket::parse(const QByteArray &data)
91{
92 if (!maybeELBTicket(data)) {
93 return {};
94 }
95
96 // check validity as strictly as possible, as ELB has no sufficiently unique marker to reliably detect it
97 // and we need to be tolerant to trailing content as there are signed variants of this in use
98
99 if (std::any_of(data.begin(), data.end(), [](char c) { return c < ' ' || c > '~'; }) || (data[19] != '0' && data[19] != '1')) {
100 return {};
101 }
102
103 ELBTicket ticket;
104 ticket.m_data = data;
105 if (ticket.barcodeVersion() != 2 || ticket.sequenceNumberCurrent() < 1 || ticket.sequenceNumberCurrent() < ticket.sequenceNumberTotal()) {
106 return {};
107 }
108 if (std::any_of(data.constData() + 35, data.constData() + 49, [](char c) { return c < '0' || c > '9'; })) {
109 return {};
110 }
111
112 if (!ticket.segment1().isValid()) {
113 return {};
114 }
115
116 return ticket;
117}
118
119
120ELBTicketSegment::~ELBTicketSegment() = default;
121
122bool ELBTicketSegment::isValid() const
123{
124 if (m_ticket.m_data.size() < m_offset + 36) {
125 return false;
126 }
127
128 return departureDay() > 0 && (classOfTransport() == QLatin1Char('1') || classOfTransport() == QLatin1Char('2'));
129}
130
131QDate ELBTicketSegment::departureDate(const QDateTime &contextDate) const
132{
133 return dateFromDayCount(departureDay() < m_ticket.emissionDay() ? m_ticket.year() + 1 : m_ticket.year(), departureDay(), contextDate);
134}
135
136QString ELBTicketSegment::readString(int start, int len) const
137{
138 return m_ticket.readString(m_offset + start, len);
139}
140
141int ELBTicketSegment::readNumber(int start, int len) const
142{
143 return m_ticket.readNumber(m_offset + start, len);
144}
145
146#include "moc_elbticket.cpp"
Segment block of an ERA ELB ticket .
Definition elbticket.h:83
ERA (Element List Barcode) ELB ticket barcode.
Definition elbticket.h:34
Q_SCRIPTABLE Q_NOREPLY void start()
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
iterator begin()
const char * constData() const const
iterator end()
qsizetype size() const const
int toInt(bool *ok, int base) const const
QDate addDays(qint64 ndays) const const
int year() const const
QDate date() const const
QString fromUtf8(QByteArrayView str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.