File indexing completed on 2024-12-29 04:51:06

0001 /*
0002    SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 // see https://community.kde.org/KDE_PIM/KItinerary/Trenitalia_Barcode
0008 function parseSsb(ssb, node) {
0009     let res = JsonLd.newTrainReservation();
0010     res.reservationFor.departureStation.name = "" + (ssb.departureStationNum % 10000000);
0011     res.reservationFor.departureStation.identifier = "uic:" + (ssb.departureStationNum % 10000000);
0012     if (ssb.departureStationNum != ssb.arrivalStationNum) {
0013         res.reservationFor.arrivalStation.name = "" + (ssb.arrivalStationNum % 10000000);
0014         res.reservationFor.arrivalStation.identifier = "uic:" + (ssb.arrivalStationNum % 10000000);
0015     }
0016     res.reservationFor.provider.identifier = "uic:" + ssb.issuerCode;
0017     if (ssb.customerNumber > 0) {
0018         res.programMembershipUsed.membershipNumber = ssb.customerNumber;
0019         res.programMembershipUsed.programName = "CartaFRECCIA";
0020     }
0021 
0022     if (ssb.firstDayOfValidityDay == ssb.lastDayOfValidityDay) {
0023         res.reservationFor.departureDay = ssb.firstDayOfValidity(node.contextDateTime)
0024     }
0025 
0026     res.reservationFor.trainNumber = ssb.readNumber(22*8 + 2, 16);
0027 
0028     const seatNum = ssb.readNumber(31*8 + 2, 7);
0029     const seatCol = ssb.readNumber(32*8 + 3, 4);
0030     if (seatNum > 0 && (seatNum != 99 || seatCol != 9)) {
0031         res.reservedTicket.ticketedSeat.seatNumber = "" + seatNum;
0032         if (seatCol > 0) {
0033             res.reservedTicket.ticketedSeat.seatNumber += seatCol.toString(16).toUpperCase();
0034         }
0035 
0036         res.reservedTicket.ticketedSeat.seatSection = ssb.readNumber(30*8 +6, 4)
0037     }
0038 
0039     res.reservationNumber = ssb.readString(33*8 + 6, 6);
0040     if (res.reservationNumber === '000000') {
0041         res.reservationNumber = ssb.readNumber(58*8 + 4, 32);
0042     }
0043 
0044     res.reservedTicket.ticketToken = "aztecbin:" + ByteArray.toBase64(ssb.rawData);
0045     return res;
0046 }
0047 
0048 function parsePdf(pdf, node, triggerNode) {
0049     let reservations = [];
0050     const page = pdf.pages[triggerNode.location];
0051     const text = page.text;
0052 
0053     var res = JsonLd.newTrainReservation();
0054     var pnr = text.match(/PNR: (\S+)/);
0055     if (pnr) {
0056         res.reservationNumber = pnr[1];
0057     }
0058 
0059     const leftHeaderText = page.textInRect(0.0, 0.15, 0.33, 0.25);
0060     const midHeaderText = page.textInRect(0.33, 0.15, 0.65, 0.25);
0061     const rightHeaderText = page.textInRect(0.65, 0.15, 1.0, 0.25);
0062 
0063     const train = rightHeaderText.match(/(?:Train|Treno|Zug)(?:\/Train)?:[ \n](.*)\n/);
0064     res.reservationFor.trainNumber = train[1];
0065 
0066     const departure_time = leftHeaderText.match(/(\d{2}:\d{2}) - (\d{2}\/\d{2}\/\d{4})/)
0067     const arrival_time = midHeaderText.match(/(\d{2}:\d{2}) - (\d{2}\/\d{2}\/\d{4})/)
0068     res.reservationFor.departureTime = JsonLd.toDateTime(departure_time[2] + departure_time[1], "dd/MM/yyyyhh:mm", "it");
0069     res.reservationFor.arrivalTime = JsonLd.toDateTime(arrival_time[2] + arrival_time[1], "dd/MM/yyyyhh:mm", "it");
0070 
0071     const dep = leftHeaderText.match(/(?:Stazione di Partenza|Departure station|Abfahrtsbahnhof|Gare de départ)(?:\/From)?\n+(.*)\n/);
0072     res.reservationFor.departureStation.name = dep[1];
0073     const arr = midHeaderText.match(/(?:Stazione di Arrivo|Arrival station|Ankunft Bahnhof|Gare d'arrivée)(?:\/To)?\n+(.*)\n/);
0074     res.reservationFor.arrivalStation.name = arr[1];
0075 
0076     const barcodes = node.findChildNodes({ scope: "Descendants", mimeType: "internal/era-ssb", field: "issuerCode", match: "83" }).concat(node.findChildNodes({ scope: "Descendants", mimeType: "internal/uic9183", field: "carrierId", match: "83" }));
0077     var offset = 0;
0078     const passengerColumn = page.textInRect(0.0, 0.3, 0.27, 1.0);
0079     let seatOffset = 0;
0080     for (let j = 0; j < barcodes.length; ++j) {
0081         if (barcodes[j].location != triggerNode.location) {
0082             continue;
0083         }
0084         let personalRes = JsonLd.clone(res);
0085         var name = passengerColumn.substr(offset).match(/(?:Passenger Name|Nome Passeggero|Nom du Passager)(?:\/Passenger\n *name)?.*\n(?:    .*\n)* *((?:\w+|\-\-).*?)(?:  |\n)/);
0086         offset += name.index + name[0].length;
0087         if (name[1] !== "--") {
0088             personalRes.underName.name = name[1];
0089         } else {
0090             personalRes.underName.name = "Passenger " + (j + 1);
0091         }
0092 
0093         var coach = text.match(/(?:Coaches|Carrozza|Wagen|Voiture)(?:\/Coach)?: +(\S+)/);
0094         if (coach) {
0095             personalRes.reservedTicket.ticketedSeat.seatSection = coach[1];
0096         }
0097 
0098         if (barcodes[j].result[0]['@type'] == 'TrainReservation') {
0099             personalRes = JsonLd.apply(barcodes[j].result[0], personalRes);
0100         } else {
0101             personalRes.reservedTicket = JsonLd.apply(barcodes[j].result[0], personalRes.reservedTicket);
0102         }
0103 
0104         // fallback seat parsing for unparsable ERA FCB tickets
0105         const seat = page.text.substr(seatOffset).match(/(\d+) +(\d+[A-F]?) +([A-Z0-9]{6})/);
0106         if (seat) {
0107             seatOffset += seat.index + seat[0].length;
0108             if (personalRes.reservedTicket.ticketedSeat.seatSection == seat[1] && !personalRes.reservedTicket.ticketedSeat.seatNumber) {
0109                 personalRes.reservedTicket.ticketedSeat.seatNumber = seat[2];
0110             }
0111         }
0112 
0113         ExtractorEngine.extractPrice(text, personalRes);
0114         reservations.push(personalRes);
0115     }
0116 
0117     return reservations;
0118 }
0119 
0120 function parseEvent(event)
0121 {
0122     let res = JsonLd.newTrainReservation();
0123     res.reservationFor.departureTime = JsonLd.readQDateTime(event, 'dtStart');
0124     res.reservationFor.arrivalTime = JsonLd.readQDateTime(event, 'dtEnd');
0125     res.reservationFor.departureStation.name = event.location;
0126     res.reservationFor.arrivalStation.name = event.description.match(event.location + "-(.*?);")[1];
0127     res.reservationFor.trainNumber = event.description.match(/Train: (.*?),/)[1];
0128     res.reservationNumber = event.description.match(/pnr code ([A-Z0-9]{6})\b/)[1];
0129     const seat = event.description.match(/Coach (.*?), Position (.*?)[;\b]/);
0130     if (seat) {
0131         res.reservedTicket.ticketedSeat.seatSection = seat[1];
0132         res.reservedTicket.ticketedSeat.seatNumber = seat[2];
0133     }
0134     return res;
0135 }