diff --git a/.gitignore b/.gitignore index 39fb081..2fa2de7 100755 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,12 @@ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures .externalNativeBuild +/app/build +/app/libs +/app/release diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser old mode 100755 new mode 100644 index d4581c9..0ac0485 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/misc.xml b/.idea/misc.xml index 99202cc..c0f68ed 100755 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,34 +1,34 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index f44f8ea..c39ecab 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,37 +1,37 @@ apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "org.dslul.ticketreader" minSdkVersion 15 targetSdkVersion 28 - versionCode 31 - versionName "2.1.6" + versionCode 33 + versionName "2.3" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { - implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:animated-vector-drawable:28.0.0' implementation 'com.android.support:support-media-compat:28.0.0' implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:customtabs:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.google.android.gms:play-services-ads:17.1.1' implementation 'com.android.support:cardview-v7:28.0.0' implementation 'com.yarolegovich:lovely-dialog:1.1.0' } diff --git a/app/release/output.json b/app/release/output.json index 89bf5d6..d4ba1fa 100755 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":20,"versionName":"2.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":33,"versionName":"2.3","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/java/org/dslul/ticketreader/ChipOnPaper.java b/app/src/main/java/org/dslul/ticketreader/ChipOnPaper.java index a046505..c4b831e 100755 --- a/app/src/main/java/org/dslul/ticketreader/ChipOnPaper.java +++ b/app/src/main/java/org/dslul/ticketreader/ChipOnPaper.java @@ -1,119 +1,124 @@ package org.dslul.ticketreader; +import android.util.Log; + import org.dslul.ticketreader.util.GttDate; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; import static org.dslul.ticketreader.util.GttDate.addMinutesToDate; import static org.dslul.ticketreader.util.HelperFunctions.getBytesFromPage; public class ChipOnPaper { private Date date; private int type; private long remainingMins; private int remainingRides; ChipOnPaper(List dumplist) { dumplist = dumplist; type = (int)getBytesFromPage(dumplist.get(5), 2, 2); long minutes = getBytesFromPage(dumplist.get(10), 0, 3); if(type == 9521) minutes = getBytesFromPage(dumplist.get(12), 0, 3); date = addMinutesToDate(minutes, GttDate.getGttEpoch()); //calcola minuti rimanenti Calendar c = Calendar.getInstance(); long diff = (c.getTime().getTime() - date.getTime()) / 60000; + long maxtime = 90; //city 100 - if(type == 302 || type == 304) { + if(type == 302 || type == 304 || type == 650) { maxtime = 100; } //Tour TODO: make a distinction between the two types if(type == 704) { maxtime = 2*24*60; } //daily if(type == 303 || type == 305) { remainingMins = GttDate.getMinutesUntilEndOfService(date); } else if(diff >= maxtime) { remainingMins = 0; } else { remainingMins = maxtime - diff; } //calcola le corse rimanenti //TODO: corse in metropolitana (forse bit piĆ¹ significativo pag. 3) int tickets; if(type == 300) { //extraurbano tickets = (int) (~getBytesFromPage(dumplist.get(3), 0, 4)); } else { tickets = (int)(~getBytesFromPage(dumplist.get(3), 2, 2)) & 0xFFFF; } remainingRides = Integer.bitCount(tickets); } public String getTypeName() { //http://www.gtt.to.it/cms/biglietti-abbonamenti/biglietti/biglietti-carnet switch (type) { case 302: case 304: return "City 100"; case 303: case 305: return "Daily"; + case 650: + return "MultiCity"; case 704: return "Tour"; case 301: return "Multicorsa extraurbano"; case 702: case 706: return "Carnet 5 corse"; case 701: case 705: return "Carnet 15 corse"; case 300: return "Extraurbano"; case 9521: return "Sadem Aeroporto Torino"; default: return "Non riconosciuto"; } } public String getDate() { return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT) .format(date); } public int getRemainingRides() { return remainingRides; } public long getRemainingMinutes() { if(remainingMins < 0) return 0; else return remainingMins; } } diff --git a/app/src/main/java/org/dslul/ticketreader/NfcThread.java b/app/src/main/java/org/dslul/ticketreader/NfcThread.java index 27f2624..5692a9c 100755 --- a/app/src/main/java/org/dslul/ticketreader/NfcThread.java +++ b/app/src/main/java/org/dslul/ticketreader/NfcThread.java @@ -1,231 +1,214 @@ package org.dslul.ticketreader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.content.Intent; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.nfc.tech.NfcA; import android.os.Handler; import android.os.Message; import android.util.Log; import static org.dslul.ticketreader.util.HelperFunctions.byteArrayToHexString; import static org.dslul.ticketreader.util.HelperFunctions.hexStringToByteArray; //parts of code from http://www.emutag.com/soft.php public class NfcThread extends Thread { private Context context; private Intent intent; private Handler mTextBufferHandler, mToastShortHandler, mToastLongHandler, mShowInfoDialogHandler; private byte[] readBuffer = new byte[1024]; // maximum theoretical capacity of MIFARE Ultralight NfcThread( Context context, Intent intent, Handler mTextBufferHandler, Handler mToastShortHandler, Handler mToastLongHandler, Handler mShowInfoDialogHandler ) { this.context = context; this.intent = intent; this.mTextBufferHandler = mTextBufferHandler; this.mToastShortHandler = mToastShortHandler; this.mToastLongHandler = mToastLongHandler; this.mShowInfoDialogHandler = mShowInfoDialogHandler; } public void run() { final Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if(tagFromIntent.getTechList()[0].equals(IsoDep.class.getName())) { handleIsoDep(tagFromIntent); } else { handleNfcA(tagFromIntent); } } private void handleIsoDep(Tag tagFromIntent) { IsoDep isoDep = IsoDep.get(tagFromIntent); if (isoDep != null) { try { isoDep.connect(); List dumplist = new ArrayList<>(); //selectApplication dumplist.add(isoDep.transceive(hexStringToByteArray("00A404000E315449432E494341D38012009101"))); //efEnvironment dumplist.add(isoDep.transceive(hexStringToByteArray("00B2013C1D"))); //efContractList dumplist.add(isoDep.transceive(hexStringToByteArray("00B201F41D"))); //efContract1 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2014C1D"))); //efContract2 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2024C1D"))); //efContract3 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2034C1D"))); //efContract4 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2044C1D"))); //efContract5 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2054C1D"))); //efContract6 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2064C1D"))); //efContract7 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2074C1D"))); //efContract8 dumplist.add(isoDep.transceive(hexStringToByteArray("00B2084C1D"))); //efEventLogs1 dumplist.add(isoDep.transceive(hexStringToByteArray("00B201441D"))); //efEventLogs2 dumplist.add(isoDep.transceive(hexStringToByteArray("00B202441D"))); //efEventLogs3 dumplist.add(isoDep.transceive(hexStringToByteArray("00B203441D"))); //efValidation dumplist.add(isoDep.transceive(hexStringToByteArray("00B201CC1D"))); -/* - dumplist.set(0, hexStringToByteArray("6F28840E315449432E494341D38012009101A516BF0C13C70800000000380712F45307062C23C00002019000")); - dumplist.set(1, hexStringToByteArray("0501030D1E7B2000026C5AAC434C4D4C534E3630433231473232344BC09000")); - dumplist.set(2, hexStringToByteArray("05012110012120012130012140012150000000000000000000000000009000")); - dumplist.set(3, hexStringToByteArray("0105000002C800000093CEBB83BEDCFFAE10AC64014437A0005485E4479000")); - dumplist.set(4, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002857A000E0E8BAA89000")); - dumplist.set(5, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002858A000292F7D039000")); - dumplist.set(6, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002859A000051117559000")); - dumplist.set(7, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C00285AA000FBDD7F709000")); - dumplist.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(10,hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(11,hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(12,hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(13,hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - dumplist.set(14,hexStringToByteArray("00000900000900000900000900000900000000000000000000000000009000")); -*/ if(dumplist.size() == 15 && dumplist.get(1)[0] != 0) { if(dumplist.get(2)[1] == 0) { showToastLong(context.getString(R.string.smartcard_empty)); return; } setContentBuffer(dumplist); showToastLong(context.getString(R.string.smartcard_read_correctly)); } else { showToastLong(context.getString(R.string.invalid_smartcard)); } isoDep.close(); } catch (IOException e) { showToastLong(context.getString(R.string.read_failure)); } } } private void handleNfcA(Tag tagFromIntent) { final NfcA mfu = NfcA.get(tagFromIntent); if (mfu == null) { showToastLong(context.getString(R.string.ticket_not_supported)); return; } byte[] ATQA = mfu.getAtqa(); if (mfu.getSak() != 0x00 || ATQA.length != 2 || ATQA[0] != 0x44 || ATQA[1] != 0x00) { showToastLong(context.getString(R.string.ticket_not_supported)); return; } int pagesRead; List dumplist = new ArrayList<>(); try { mfu.connect(); pagesRead = rdNumPages(mfu, 16); // 0 for no limit (until error) mfu.close(); for (int i = 0; i < pagesRead*4; i += 4) { byte[] mfuPage = new byte[4]; System.arraycopy(readBuffer, i, mfuPage, 0, 4); dumplist.add(mfuPage); } if(pagesRead >= 16) { showToastShort(context.getString(R.string.ticket_correctly_read)); setContentBuffer(dumplist); } else { throw new RuntimeException(context.getString(R.string.read_failure)); } } catch (RuntimeException e) { showToastLong(context.getString(R.string.read_failure)); } catch (Exception e) { showToastLong(context.getString(R.string.communication_error)); } } private void setContentBuffer(List content) { Message msg = new Message(); msg.obj = content; mTextBufferHandler.sendMessage(msg); } private void showToastShort(String text) { Message msg = new Message(); msg.obj = text; mToastShortHandler.sendMessage(msg); } private void showToastLong(String text) { Message msg = new Message(); msg.obj = text; mToastLongHandler.sendMessage(msg); } private void showInfoDialog(String text) { Message msg = new Message(); msg.obj = text; mShowInfoDialogHandler.sendMessage(msg); } private int rdNumPages(NfcA mfu, int num) { int pagesRead = 0; while (rdPages(mfu, pagesRead) == 0) { pagesRead++; if (pagesRead == num || pagesRead == 256) break; } return pagesRead; } // first failure (NAK) causes response 0x00 (or possibly other 1-byte values) // second failure (NAK) causes transceive() to throw IOException private byte rdPages(NfcA tag, int pageOffset) { byte[] cmd = {0x30, (byte)pageOffset}; byte[] response = new byte[16]; try { response = tag.transceive(cmd); } catch (IOException e) { return 1; } if (response.length != 16) return 1; System.arraycopy(response, 0, readBuffer, pageOffset * 4, 4); return 0; } } diff --git a/app/src/main/java/org/dslul/ticketreader/SmartCard.java b/app/src/main/java/org/dslul/ticketreader/SmartCard.java index 50c713e..1486a3e 100644 --- a/app/src/main/java/org/dslul/ticketreader/SmartCard.java +++ b/app/src/main/java/org/dslul/ticketreader/SmartCard.java @@ -1,372 +1,331 @@ package org.dslul.ticketreader; import android.util.Log; import org.dslul.ticketreader.util.GttDate; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import static java.lang.Math.abs; import static org.dslul.ticketreader.util.HelperFunctions.getBytesFromPage; public class SmartCard { public enum Type { BIP, PYOU, EDISU } - static final Map subscriptionCodes = new HashMap() {{ + private static final Map subscriptionCodes = new HashMap() {{ put(68, "Mensile UNDER 26"); put(72, "Mensile Studenti Rete Urbana"); put(101, "Settimanale Formula 1"); put(102, "Settimanale Formula 2"); put(103, "Settimanale Formula 3"); put(104, "Settimanale Formula 4"); put(105, "Settimanale Formula 5"); put(106, "Settimanale Formula 6"); put(107, "Settimanale Formula 7"); put(108, "Settimanale Intera Area Formula"); put(109, "Settimanale Personale Rete Urbana"); put(199, "Mensile Personale Rete Urbana (Formula U)"); put(201, "Mensile Formula 1"); put(202, "Mensile Formula 2"); put(203, "Mensile Formula 3"); put(204, "Mensile Formula 4"); put(205, "Mensile Formula 5"); put(206, "Mensile Formula 6"); put(207, "Mensile Formula 7"); put(208, "Mensile Intera Area Formula"); put(261, "Mensile Studenti Urbano+Suburbano"); put(290, "Mensile 65+ Urbano Orario Ridotto"); put(291, "Mensile 65+ Urbano"); put(307, "Annuale Ivrea Rete Urbana e Dintorni"); put(308, "Annuale Extraurbano O/D"); put(310, "Plurimensile Studenti Extraurbano O/D"); put(721, "Annuale UNDER 26"); put(722, "Annuale UNDER 26 Fascia A"); put(723, "Annuale UNDER 26 Fascia B"); put(724, "Annuale UNDER 26 Fascia C"); put(730, "Mensile urbano Over 65"); put(761, "Annuale Over A"); put(731, "Annuale Over B"); put(732, "Annuale Over C"); put(733, "Annuale Over D"); put(911, "10 Mesi Studenti"); put(912, "Annuale Studenti"); put(990, "Junior"); put(993, "Annuale Formula U"); put(4001, "Settimanale Formula 4"); put(4002, "Mensile Formula 3 U+A"); put(4003, "Annuale Formula U a Zone"); }}; - static final Map ticketCodes = new HashMap() {{ + private static final Map ticketCodes = new HashMap() {{ put(712, "Ordinario Urbano"); put(714, "City 100"); put(715, "Daily"); put(716, "Multidaily"); }}; private class Contract { private int code; private int counters; private boolean isValid; private boolean isTicket; private boolean isSubscription; private Date startDate; private Date endDate; - public Contract(byte[] data, int counters) { + Contract(byte[] data, int counters) { int company = data[0]; this.counters = counters; //get contract type code = ((data[4] & 0xff) << 8) | data[5] & 0xff; //support for GTT S.p.A. tickets only for now if(code == 0 || company != 1) { isValid = false; } else { isValid = true; } if(ticketCodes.containsKey(code)) { isTicket = true; isSubscription = false; } else if(subscriptionCodes.containsKey(code)) { isTicket = false; isSubscription = true; } else { isTicket = false; isSubscription = false; } long minutes = ~(data[9] << 16 & 0xff0000 | data[10] << 8 & 0xff00 | data[11] & 0xff) & 0xffffff; startDate = GttDate.decode(minutes); minutes = ~(data[12] << 16 & 0xff0000 | data[13] << 8 & 0xff00 | data[14] & 0xff) & 0xffffff; endDate = GttDate.decode(minutes); } public int getCode() { return code; } public Date getStartDate() { return startDate; } - public int getRides() { + int getRides() { if(code == 712 || code == 714) return (((counters & 0x0000ff)&0x78) >> 3); else return (counters >> 19); } - public Date getEndDate() { + Date getEndDate() { return endDate; } - public boolean isContract() { + boolean isContract() { return isValid; } - public boolean isSubscription() { - if(isSubscription) - return true; - else - return false; + boolean isSubscription() { + return isSubscription; } - public boolean isTicket() { - if(isTicket) - return true; - else - return false; + boolean isTicket() { + return isTicket; } - public String getTypeName() { + String getTypeName() { if(isTicket) return ticketCodes.get(code); else if(isSubscription) return subscriptionCodes.get(code); else return "Sconosciuto"; } } private Date validationDate; private Date creationDate; private Type type; private List tickets = new ArrayList<>(); private List subscriptions = new ArrayList<>(); private Contract subscription; private int ridesLeft = 0; private long remainingMins; SmartCard(List dumplist) { byte[] selectApplication = dumplist.get(0); byte[] efEnvironment = dumplist.get(1); byte[] efContractList = dumplist.get(2); byte[] efEventLogs1 = dumplist.get(11); byte[] efEventLogs2 = dumplist.get(12); byte[] efEventLogs3 = dumplist.get(13); byte[] efCounters = dumplist.get(14); if(efEnvironment[28] == (byte)0xC0) type = Type.BIP; else if(efEnvironment[28] == (byte)0xC1) type = Type.PYOU; else if(efEnvironment[28] == (byte)0xC2) type = Type.EDISU; byte[] minutes = new byte[3]; System.arraycopy(efEnvironment, 9, minutes, 0, 3); creationDate = GttDate.decode(minutes); //scan contractlist for tickets and subscriptions for(int i = 1; i < 23; i+=3) { //only GTT tickets atm if(efContractList[i] == 1) { //check validity if((efContractList[i+1]&0x0f) == 1) { //position in counters int cpos = ((abs(efContractList[i+2]&0xff) >> 4)-1)*3; int counter = 0; if(cpos >= 0) counter = (efCounters[cpos+2] & 0xff) | ((efCounters[cpos+1] & 0xff) << 8) | ((efCounters[cpos] & 0xff) << 16); - Log.d("card", String.valueOf(counter >> 19)); Contract contract = new Contract(dumplist.get(i/3+1 + 2), counter); if(contract.isContract()) { if(contract.isSubscription()) { subscriptions.add(contract); } if(contract.isTicket()) { tickets.add(contract); ridesLeft += contract.getRides(); } } } } } - /* - for (int i = 0; i < 8; i++) { - Contract contract = new Contract(dumplist.get(i+3)); - - if(contract.isContract()) { - if(contract.isSubscription()) { - subscriptions.add(contract); - } - if(contract.isTicket()) { - tickets.add(contract); - } - } - - */ - //get a valid subscription, if there's any Date latestExpireDate = GttDate.getGttEpoch(); for (Contract sub : subscriptions) { if (latestExpireDate.before(sub.getEndDate())) { latestExpireDate = sub.getEndDate(); subscription = sub; } } - //actual tickets count - //ridesLeft = countTickets(efCounters, efContractList); - //get last validation time long mins = getBytesFromPage(efEventLogs1, 20, 3); if(mins == 0) mins = getBytesFromPage(efEventLogs2, 20, 3); if(mins == 0) mins = getBytesFromPage(efEventLogs3, 20, 3); validationDate = GttDate.addMinutesToDate(mins, GttDate.getGttEpoch()); Calendar c = Calendar.getInstance(); long diff = (c.getTime().getTime() - validationDate.getTime()) / 60000; int num = (int)(getBytesFromPage(efEventLogs1, 25, 1) >> 4); int tickettype = (int)getBytesFromPage(dumplist.get(num+2), 4, 2); long maxtime = 90; //city 100 if(tickettype == 714) { maxtime = 100; } //daily if(tickettype == 715 || tickettype == 716) { remainingMins = GttDate.getMinutesUntilEndOfService(validationDate); } else if(diff >= maxtime) { remainingMins = 0; } else { remainingMins = maxtime - diff; } } - private int countTickets(byte[] validations, byte[] contractsList) { - int count = 0; - for (int i = 2; i < 24; i+=3) { - int valpos = abs(contractsList[i+1]) >> 4; - //position in contractslist - int pos = i/3 + 1; - //check if it's a subscription - int sub = abs(contractsList[i]&0xf0) >> 4; - if(pos > 0 && pos <= 8 && (contractsList[i]&0x0f) != 0 && sub < 0xA) { - int rides = (abs(validations[valpos*3-3] & 0xff) >> 3); - count += rides; - } - } - return count; - } - public String getTicketName() { if(hasTickets()) return type + " - " + tickets.get(0).getTypeName(); else return type.toString(); } public String getSubscriptionName() { if(hasSubscriptions()) return type + " - " + subscription.getTypeName(); else return type.toString(); } public boolean hasTickets() { - return ridesLeft != 0; + return ridesLeft != 0 || remainingMins > 0; } public boolean hasSubscriptions() { return subscriptions.size() != 0; } public String getExpireDate() { return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT) .format(subscription.getEndDate()); } public String getValidationDate() { return DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT) .format(validationDate); } public boolean isSubscriptionExpired() { Calendar c = Calendar.getInstance(); return c.getTime().after(subscription.getEndDate()); } private boolean isExpired(Date date) { Calendar c = Calendar.getInstance(); return c.getTime().after(date); } public int getRemainingRides() { return ridesLeft; } public long getRemainingMinutes() { if(remainingMins < 0) return 0; else return remainingMins; } } diff --git a/app/src/main/java/org/dslul/ticketreader/util/GttDate.java b/app/src/main/java/org/dslul/ticketreader/util/GttDate.java index f730b9c..cf8e2ff 100644 --- a/app/src/main/java/org/dslul/ticketreader/util/GttDate.java +++ b/app/src/main/java/org/dslul/ticketreader/util/GttDate.java @@ -1,67 +1,94 @@ package org.dslul.ticketreader.util; import android.util.Log; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; +import java.util.concurrent.TimeUnit; public final class GttDate { public static Date decode(byte[] minutes) { return addMinutesToDate(byteArrayToLong(minutes), getGttEpoch()); } public static Date decode(long minutes) { return addMinutesToDate(minutes, getGttEpoch()); } public static Date getGttEpoch() { String startingDate = "05/01/01 00:00:00"; SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); Date date = null; try { date = format.parse(startingDate); } catch (ParseException e) { e.printStackTrace(); } return date; } public static long getMinutesUntilEndOfService(Date startDate) { Calendar curr = Calendar.getInstance(); Calendar after = Calendar.getInstance(); Calendar start = Calendar.getInstance(); start.setTime(startDate); + if((curr.getTimeInMillis() - start.getTimeInMillis())/60000 > 24*60) { + return 0; + } int dayoff = 0; if(start.get(Calendar.DAY_OF_MONTH) == curr.get(Calendar.DAY_OF_MONTH)) dayoff = 1; after.add(Calendar.DAY_OF_MONTH, dayoff); after.set(Calendar.HOUR_OF_DAY, 3); after.set(Calendar.MINUTE, 0); after.set(Calendar.SECOND, 0); after.set(Calendar.MILLISECOND, 0); return (after.getTimeInMillis() - curr.getTimeInMillis())/60000; } public static Date addMinutesToDate(long minutes, Date beforeTime) { final long ONE_MINUTE_IN_MILLIS = 60000; long curTimeInMs = beforeTime.getTime(); return new Date(curTimeInMs + (minutes * ONE_MINUTE_IN_MILLIS)); } private static long byteArrayToLong(byte[] bytes) { long value = 0; for (int i = 0; i < bytes.length; i++) { value = (value << 8) + (bytes[i] & 0xff); } return value; } + //only for unit testing + public static String genDate() { + + String dateStart = "05/01/01 00:00:00"; + Date now = new Date(); + SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); + Date d1 = null; + Date d2 = new Date(); + try { + d1 = format.parse(dateStart); + } catch (ParseException e) { + e.printStackTrace(); + } + long diff = d2.getTime() - d1.getTime(); + long diffMinutes = diff / (60 * 1000) % 60; + + String page = Long.toHexString(TimeUnit.MILLISECONDS.toMinutes(diff)); + for (int i = 0; i <= 8 - page.length(); i++) { + page += "0"; + } + return page; + } + } diff --git a/app/src/test/java/org/dslul/ticketreader/ChipOnPaperUnitTest.java b/app/src/test/java/org/dslul/ticketreader/ChipOnPaperUnitTest.java deleted file mode 100755 index fbc6a60..0000000 --- a/app/src/test/java/org/dslul/ticketreader/ChipOnPaperUnitTest.java +++ /dev/null @@ -1,145 +0,0 @@ -package org.dslul.ticketreader; - -import android.test.AndroidTestCase; -import android.test.ApplicationTestCase; -import android.test.InstrumentationTestCase; -import android.util.Log; - -import org.dslul.ticketreader.util.HelperFunctions; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.List; - -import static org.dslul.ticketreader.util.HelperFunctions.hexStringToByteArray; -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ChipOnPaperUnitTest { - - List ticket2 = new ArrayList<>(); - List ticket3 = new ArrayList<>(); - List ticket4 = new ArrayList<>(); - List ticket5 = new ArrayList<>(); - List ticket6 = new ArrayList<>(); - - @Test - public void ChipOnPaper_isCorrect() throws Exception { - List ticket1 = new ArrayList<>(); - ticket1.add(hexStringToByteArray("057D6292")); - ticket1.add(hexStringToByteArray("AD2954E9")); - ticket1.add(hexStringToByteArray("3915F203")); - ticket1.add(hexStringToByteArray("07FFFFF0")); - ticket1.add(hexStringToByteArray("01040000")); - ticket1.add(hexStringToByteArray("020102BE")); - ticket1.add(hexStringToByteArray("68970000")); - ticket1.add(hexStringToByteArray("00AE10A7")); - ticket1.add(hexStringToByteArray("0200645C")); - ticket1.add(hexStringToByteArray("397D91B4")); - ticket1.add(hexStringToByteArray("68A4F900")); - ticket1.add(hexStringToByteArray("04F80000")); - ticket1.add(hexStringToByteArray("68A4F900")); - ticket1.add(hexStringToByteArray("00050004")); - ticket1.add(hexStringToByteArray("F8AE1079")); - ticket1.add(hexStringToByteArray("9E1291E4")); - ChipOnPaper chip = new ChipOnPaper(ticket1); - assertEquals(4, chip.getRemainingRides()); - assertEquals(0, chip.getRemainingMinutes()); - - } - - @Test - public void Smartcard_Count_Ticket_isCorrect() throws Exception { - List list = new ArrayList<>(); - list.add(hexStringToByteArray("6F208970ABA0B980986C9A09078F098087E0A980DF0101010A0101090E109019011022354345676010019000")); - list.add(hexStringToByteArray("050110129845479323849432659823874899264578987A09A9692348799000")); - - list.add(hexStringToByteArray("05012160014020014030014040014050012110012170012180000000009000")); - - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - - list.add(hexStringToByteArray("0501000000216D7F0D0004F800002A00000000006D7F0D00007000BEE39000")); - list.add(hexStringToByteArray("0501000000216D00050004F800000400000000006CFFF00000400007779000")); - list.add(hexStringToByteArray("0501000000216CFFF00004F80000D800000000006CFFF000004000316A9000")); - - list.add(hexStringToByteArray("60000234D95D6F5840000000000060004000004000000000234321E56A821000019000")); - SmartCard smartcard = new SmartCard(list); - - assertEquals(3, smartcard.getRemainingRides()); - - list.set(2, hexStringToByteArray("05012160014020014030014040014050012110012170012180000000009000")); - list.set(11, hexStringToByteArray("0501000000216D959E0004F800002A00000000006D959E00001000674E9000")); - list.set(12, hexStringToByteArray("0501000000216D7F0D0004F800002A00000000006D7F0D00007000BEE39000")); - list.set(13, hexStringToByteArray("0501000000216D00050004F800000400000000006CFFF00000400007779000")); - SmartCard s2 = new SmartCard(list); - - assertEquals(2, s2.getRemainingRides()); - - - list.set(2, hexStringToByteArray("05012060014020014030014040014050012110012170012180000000009000")); - list.set(11, hexStringToByteArray("0501000000216D9B2C0004F800002A00000000006D9B2C000060008D809000")); - list.set(12, hexStringToByteArray("0501000000216D959E0004F800002A00000000006D959E00001000674E9000")); - list.set(13, hexStringToByteArray("0501000000216D7F0D0004F800002A00000000006D7F0D00007000BEE39000")); - smartcard = new SmartCard(list); - - assertEquals(1, smartcard.getRemainingRides()); - - - list.set(2, hexStringToByteArray("05012060014020014030014040014050012110012170012180000000009000")); - list.set(11, hexStringToByteArray("0501000000216D9B2C0004F800002A00000000006D9B2C000060008D809000")); - list.set(12, hexStringToByteArray("0501000000216D959E0004F800002A00000000006D959E00001000674E9000")); - list.set(13, hexStringToByteArray("0501000000216D7F0D0004F800002A00000000006D7F0D00007000BEE39000")); - smartcard = new SmartCard(list); - - assertEquals(1, smartcard.getRemainingRides()); - - //1 used ticket - list.set(2, hexStringToByteArray("05012110000000000000000000000000000000000000000000000000009000")); - list.set(11, hexStringToByteArray("0501000000216C9EF30004F800007400000000006C9EB100001000F66B9000")); - list.set(12, hexStringToByteArray("0501000000216C9EC80004F80003E700000000006C9EB100001000E9E29000")); - list.set(13, hexStringToByteArray("0501000000216C9EB10004F800007400000000006C9EB10000100098509000")); - smartcard = new SmartCard(list); - - assertEquals(0, smartcard.getRemainingRides()); - - - //1 used ticket - list.set(2, hexStringToByteArray("05012110000000000000000000000000000000000000000000000000009000")); - list.set(11, hexStringToByteArray("0501000000216C9EF30004F800007400000000006C9EB100001000F66B9000")); - list.set(12, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - list.set(13, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); - smartcard = new SmartCard(list); - - assertEquals(0, smartcard.getRemainingRides()); - - //1 full multidaily - list.set(2, hexStringToByteArray("0501A10001511001A100000000000000000000000000000000000000009000")); - list.set(11, hexStringToByteArray("0501030258216C41130004F800007400000000006C355D0000300017D89000")); - list.set(12, hexStringToByteArray("0501030258216C3F8A0004F800000F00000000006C355D000030002EE19000")); - list.set(13, hexStringToByteArray("0501030258216C356A0004F800000A00000000006C355D000030007F249000")); - smartcard = new SmartCard(list); - - assertEquals(7, smartcard.getRemainingRides()); - - - //expired subscriptions only - list.set(2, hexStringToByteArray("0501A10001000001A100000000000000000000000000000000000000009000")); - list.set(11, hexStringToByteArray("0501030258216C41130004F800007400000000006C355D0000300017D89000")); - list.set(12, hexStringToByteArray("0501030258216C3F8A0004F800000F00000000006C355D000030002EE19000")); - list.set(13, hexStringToByteArray("0501030258216C356A0004F800000A00000000006C355D000030007F249000")); - smartcard = new SmartCard(list); - - assertEquals(false, smartcard.hasTickets()); - } -} \ No newline at end of file diff --git a/app/src/test/java/org/dslul/ticketreader/TicketsUnitTest.java b/app/src/test/java/org/dslul/ticketreader/TicketsUnitTest.java new file mode 100755 index 0000000..457e90d --- /dev/null +++ b/app/src/test/java/org/dslul/ticketreader/TicketsUnitTest.java @@ -0,0 +1,314 @@ +package org.dslul.ticketreader; + + +import org.dslul.ticketreader.util.GttDate; +import org.junit.Test; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.dslul.ticketreader.util.HelperFunctions.hexStringToByteArray; +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class TicketsUnitTest { + + @Test + public void ChipOnPaper_isCorrect() { + List ticket1 = new ArrayList<>(); + ticket1.add(hexStringToByteArray("057D6292")); + ticket1.add(hexStringToByteArray("AD2954E9")); + ticket1.add(hexStringToByteArray("3915F203")); + ticket1.add(hexStringToByteArray("07FFFFF0")); + ticket1.add(hexStringToByteArray("01040000")); + ticket1.add(hexStringToByteArray("020102BE")); + ticket1.add(hexStringToByteArray("68970000")); + ticket1.add(hexStringToByteArray("00AE10A7")); + ticket1.add(hexStringToByteArray("0200645C")); + ticket1.add(hexStringToByteArray("397D91B4")); + ticket1.add(hexStringToByteArray("68A4F900")); + ticket1.add(hexStringToByteArray("04F80000")); + ticket1.add(hexStringToByteArray("68A4F900")); + ticket1.add(hexStringToByteArray("00050004")); + ticket1.add(hexStringToByteArray("F8AE1079")); + ticket1.add(hexStringToByteArray("9E1291E4")); + ChipOnPaper chip = new ChipOnPaper(ticket1); + assertEquals(4, chip.getRemainingRides()); + assertEquals(0, chip.getRemainingMinutes()); + + + ticket1.set(0, hexStringToByteArray("043FDA69")); + ticket1.set(1, hexStringToByteArray("AAD75B81")); + ticket1.set(2, hexStringToByteArray("A748F203")); + ticket1.set(3, hexStringToByteArray("7FFFFFFF")); + ticket1.set(4, hexStringToByteArray("010B0000")); + ticket1.set(5, hexStringToByteArray("0101012F")); + ticket1.set(6, hexStringToByteArray("6F072000")); + ticket1.set(7, hexStringToByteArray("00AE10A7")); + ticket1.set(8, hexStringToByteArray("F1006A3D")); + ticket1.set(9, hexStringToByteArray("99EE380F")); + ticket1.set(10, hexStringToByteArray("6F09BE00")); + ticket1.set(11, hexStringToByteArray("04F80000")); + ticket1.set(12, hexStringToByteArray("6F09BE00")); + ticket1.set(13, hexStringToByteArray("00D80004")); + ticket1.set(14, hexStringToByteArray("F8AE10A0")); + ticket1.set(15, hexStringToByteArray("02121827")); + chip = new ChipOnPaper(ticket1); + assertEquals(0, chip.getRemainingRides()); + assertEquals(0, chip.getRemainingMinutes()); + + + ticket1.set(0, hexStringToByteArray("04CF7132")); + ticket1.set(1, hexStringToByteArray("1A675D80")); + ticket1.set(2, hexStringToByteArray("A048F203")); + ticket1.set(3, hexStringToByteArray("7FFFFFFF")); + ticket1.set(4, hexStringToByteArray("01030000")); + ticket1.set(5, hexStringToByteArray("0101012E")); + ticket1.set(6, hexStringToByteArray("6C0FC000")); + ticket1.set(7, hexStringToByteArray("00AE112F")); + ticket1.set(8, hexStringToByteArray("C9000152")); + ticket1.set(9, hexStringToByteArray("A22C4C8E")); + ticket1.set(10, hexStringToByteArray("6C958400")); + ticket1.set(11, hexStringToByteArray("04F80000")); + ticket1.set(12, hexStringToByteArray("6C958400")); + ticket1.set(13, hexStringToByteArray("000F0004")); + ticket1.set(14, hexStringToByteArray("F8AE10FE")); + ticket1.set(15, hexStringToByteArray("C7123D71")); + chip = new ChipOnPaper(ticket1); + assertEquals(0, chip.getRemainingRides()); + assertEquals(0, chip.getRemainingMinutes()); + + + ticket1.set(10, hexStringToByteArray(GttDate.genDate())); + chip = new ChipOnPaper(ticket1); + assertEquals(100, chip.getRemainingMinutes()); + } + + @Test + public void Smartcard_Count_Ticket_isCorrect() { + List list = new ArrayList<>(); + list.add(hexStringToByteArray("6F208970ABA0B980986C9A09078F098087E0A980DF0101010A0101090E109019011022354345676010019000")); + list.add(hexStringToByteArray("0501030C72BF2000026B0CC4435354504C413639423632443936394DC09000")); + list.add(hexStringToByteArray("05010100016010016120000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("01050000000000000094F33B94ED9CFFAE10AC40007661A00092EB6D539000")); + list.add(hexStringToByteArray("0105000002CC000000930F7B8B267CFFAE10A71800F7BFA000B8CC23E69000")); + list.add(hexStringToByteArray("0105000002CC0000009228DB8A3FDCFFAE10A718011440A000F722D0509000")); + list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.add(hexStringToByteArray("0501000000216E34F700000B00032100000000006E34F700003000E7BC9000")); + list.add(hexStringToByteArray("0501000000216E347B00001400032100000000006E347B000030008A999000")); + list.add(hexStringToByteArray("0501000000216E329D00000700032100000000006E329D0000300083079000")); + list.add(hexStringToByteArray("06D3DD37A48600000000000000000000000000000000000000000000009000")); + SmartCard smartcard = new SmartCard(list); + + assertEquals(6, smartcard.getRemainingRides()); + + list.set(1, hexStringToByteArray("0501030C72BB2000026B0CC4535643534C5630315035304C32313941C09000")); + list.set(2, hexStringToByteArray("05010100016010016120000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("01050000000000000094F33B94ED9CFFAE10AC40007660A00012425D4A9000")); + list.set(4, hexStringToByteArray("0105000002CC000000930F7B8B267CFFAE10A71800F7C0A0003DE647B39000")); + list.set(5, hexStringToByteArray("0105000002CC0000009228DB8A3FDCFFAE10A718011441A0008AD75F7F9000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216E3B7600000700032100000000006E3B76000030001BD19000")); + list.set(12, hexStringToByteArray("0501000000216E1DCD00000B00032100000000006E1DCD00003000D3669000")); + list.set(13, hexStringToByteArray("0501000000216E194200000F00032100000000006E194200003000089A9000")); + list.set(14, hexStringToByteArray("06F4161F9BAD00000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(3, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("0501030BE11820000269F05D524D4E42524E36314530384C3231394FC09000")); + list.set(2, hexStringToByteArray("05014120014110000000000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("0105000002CB000000921D9B8A349CFFAE10A3CA00A4CCA00025EFFF919000")); + list.set(4, hexStringToByteArray("0105000002CB000000921D9B8A349CFFAE10A3CA00A4CDA000E885A0709000")); + list.set(5, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(12, hexStringToByteArray("0501000000216DE5E60004F800000900000000006DE59D00001000A5079000")); + list.set(13, hexStringToByteArray("0501000000216DE5E20004F800000900000000006DE59D00001000D1C69000")); + list.set(14, hexStringToByteArray("0FFFFF0FFFFF00000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(2, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("0501030C544E2000026AFE93424E5444564436334130364439333348C09000")); + list.set(2, hexStringToByteArray("05016120000000000000000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("0105000002CC00000092DCDB8AF3DCFFAE10A6B800AEFBA00045509B0E9000")); + list.set(4, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(5, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216DDB0E0004F80003E700000000006DD8A900001000F0639000")); + list.set(12, hexStringToByteArray("0501000000216DD8A90004F800004700000000006DD8A900001000EF2A9000")); + list.set(13, hexStringToByteArray("0501000000216D653E0004F800004700000000006D62A80000100092DC9000")); + list.set(14, hexStringToByteArray("000000274A7A00000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(4, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("05010304CEBD2010023E3F64534C4D4E544E3934413135413834314FC29000")); + list.set(2, hexStringToByteArray("0501A100000000000000000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("010503900390000000C27A3BBA751BFFAE10AC480002AEA0005C37C9E19000")); + list.set(4, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(5, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000214410E000000B00032100000000004410E000000000EB969000")); + list.set(12, hexStringToByteArray("05010000002143D37700000D000321000000000043D3770000000048749000")); + list.set(13, hexStringToByteArray("0501000000214313F500000D00032100000000004313F50000000068FA9000")); + list.set(14, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(0, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("05010304864E2010023DA7844C444E444E4C39334D30384638393245C29000")); + list.set(2, hexStringToByteArray("0501A10001611001A100000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("010503900390000000C27A3BBA751BFFAE1045EC00004AA000271C893D9000")); + list.set(4, hexStringToByteArray("0105000002CC00000092233B8A3A3CFFAE10A7F10052A3A000065CFC0B9000")); + list.set(5, hexStringToByteArray("01050000038F0302589A5AFB93B29CFFAE10FEC000007FA00003D605A29000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216E175E0004F800000C00000000006E175E00002000E9AA9000")); + list.set(12, hexStringToByteArray("0501000000216DFD4D0004F800000A00000000006DFD3600002000832A9000")); + list.set(13, hexStringToByteArray("0501000000216DFD3600000100032100000000006DFD360000200057569000")); + list.set(14, hexStringToByteArray("2FC56500000000000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(5, smartcard.getRemainingRides()); + + + list.set(0, hexStringToByteArray("6F28840E315449432E494341D38012009101A516BF0C13C70800000000381ADC645307063C23C01010019000")); + list.set(1, hexStringToByteArray("0501030D1E7B2000026C5AAC434C4D4C534E3630433231473232344BC09000")); + list.set(2, hexStringToByteArray("05012110012120012130012140012150000000000000000000000000009000")); + list.set(3, hexStringToByteArray("0105000002C800000093CEBB83BEDCFFAE10AC64014437A0005485E4479000")); + list.set(4, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002857A000E0E8BAA89000")); + list.set(5, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002858A000292F7D039000")); + list.set(6, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C002859A000051117559000")); + list.set(7, hexStringToByteArray("0105000002CA00000091B85B81AE1CFFAE10AA0C00285AA000FBDD7F709000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(12, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(13, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(14, hexStringToByteArray("00000900000900000900000900000900000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(5, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("05010304864E2010023DA7844C444E444E4C39334D30384638393245C29000")); + list.set(2, hexStringToByteArray("0501A10001611001A100014120000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("010503900390000000C27A3BBA751BFFAE1045EC00004AA000271C893D9000")); + list.set(4, hexStringToByteArray("0105000002CC00000092233B8A3A3CFFAE10A7F10052A3A000065CFC0B9000")); + list.set(5, hexStringToByteArray("01050000038F0302589A5AFB93B29CFFAE10FEC000007FA00003D605A29000")); + list.set(6, hexStringToByteArray("0105000002CB00000090501F886720FFAE10A7BD007D57A000C743C9519000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216F98540004F800000F00000000006F979900002000D87B9000")); + list.set(12, hexStringToByteArray("0501000000216F97990004F800000F00000000006F97990000200051459000")); + list.set(13, hexStringToByteArray("0501000000216EFB420004F800000F00000000006EF8870000200015E39000")); + list.set(14, hexStringToByteArray("0645660FFFFF00000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(1, smartcard.getRemainingRides()); + assertEquals("EDISU - Daily", smartcard.getTicketName()); + + + list.set(1, hexStringToByteArray("05010304864E2010023DA7844C444E444E4C39334D30384638393245C29000")); + list.set(2, hexStringToByteArray("0501A10001601001A100014120000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("010503900390000000C27A3BBA751BFFAE1045EC00004AA000271C893D9000")); + list.set(4, hexStringToByteArray("0105000002CC00000092233B8A3A3CFFAE10A7F10052A3A000065CFC0B9000")); + list.set(5, hexStringToByteArray("01050000038F0302589A5AFB93B29CFFAE10FEC000007FA00003D605A29000")); + list.set(6, hexStringToByteArray("0105000002CB00000090501F886720FFAE10A7BD007D57A000C743C9519000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216FB3A20004F800000F00000000006FB3A200004000210C9000")); + list.set(12, hexStringToByteArray("0501000000216F98540004F800000F00000000006F979900002000D87B9000")); + list.set(13, hexStringToByteArray("0501000000216F97990004F800000F00000000006F97990000200051459000")); + list.set(14, hexStringToByteArray("06456607FC3D00000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertEquals(0, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("050103089E8D2000025DC1A4524E44524C4130304432324C32313959C19000")); + list.set(2, hexStringToByteArray("0501A00001F00001A10001F10001A00001F000000000000000000000009000")); + list.set(3, hexStringToByteArray("010500000FA100000094231B93FBBCFFAE10AC7000D9B0A0026D5A4AC69000")); + list.set(4, hexStringToByteArray("F110060000000000000051504F415500000000000000000000BA9E15609000")); + list.set(5, hexStringToByteArray("010500000FA100000091FBDB91D47CFFAE10AD3A005C23A00426C74CDE9000")); + list.set(6, hexStringToByteArray("F130040000000000000051504F41000000000000000000000071AB2ADB9000")); + list.set(7, hexStringToByteArray("010500000FA100000096717F964A20FFAE10ACB40042C6A006ECF2BC6E9000")); + list.set(8, hexStringToByteArray("F150040000000000000051504F4100000000000000000000008A523C0E9000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("0501000000216E05DE0004490005E600000000006E05DE0000300017379000")); + list.set(12, hexStringToByteArray("0501000000216BF78A0004000005E600000000006BE44200001000EAB79000")); + list.set(13, hexStringToByteArray("0501000000216BF75E0004F800002200000000006BE4420000100059469000")); + list.set(14, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertFalse(smartcard.hasTickets()); + assertTrue(smartcard.hasSubscriptions()); + assertEquals(0, smartcard.getRemainingRides()); + + + list.set(1, hexStringToByteArray("0501030888942011F24E44044C4D544652433931443539433334324FC29000")); + list.set(2, hexStringToByteArray("0501A100010100014110000000000000000000000000000000000000009000")); + list.set(3, hexStringToByteArray("0105000003E10388A096609F8E5B80FFAE10FE4F0000A0A000674A13489000")); + list.set(4, hexStringToByteArray("0105000003900130FDAA6ADBA2601CFFAE1046110016DAA00032711AF99000")); + list.set(5, hexStringToByteArray("0105000002CB00000092887B8A9F7CFFAE10AAE8003EBAA00037DBB1FE9000")); + list.set(6, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(7, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(8, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(9, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(10, hexStringToByteArray("00000000000000000000000000000000000000000000000000000000009000")); + list.set(11, hexStringToByteArray("05010388A0216E1EBA0004F800001200000000006D95A700001000FA1A9000")); + list.set(12, hexStringToByteArray("05010388A0216DF7540004F800004400000000006D95A70000100091A49000")); + list.set(13, hexStringToByteArray("05010388A0216DCDFA0004F800000400000000006D95A70000100041CD9000")); + list.set(14, hexStringToByteArray("07FDFA00000000000000000000000000000000000000000000000000009000")); + smartcard = new SmartCard(list); + + assertFalse(smartcard.hasTickets()); + assertTrue(smartcard.hasSubscriptions()); + assertEquals(0, smartcard.getRemainingRides()); + + + } + + +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4b9ed6e..e9cd780 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Apr 12 12:46:27 CEST 2018 +#Sat Dec 01 10:58:45 CET 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip