diff --git a/src/it/reyboz/bustorino/adapters/AdapterListener.java b/src/it/reyboz/bustorino/adapters/AdapterListener.java
--- a/src/it/reyboz/bustorino/adapters/AdapterListener.java
+++ b/src/it/reyboz/bustorino/adapters/AdapterListener.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Adapter components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.adapters;
import it.reyboz.bustorino.backend.Stop;
diff --git a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
--- a/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/PalinaAdapter.java
@@ -30,15 +30,15 @@
import android.widget.ArrayAdapter;
import android.widget.TextView;
- import java.util.List;
+import java.util.List;
import java.util.Locale;
-import it.reyboz.bustorino.BuildConfig;
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Palina;
import it.reyboz.bustorino.backend.Passaggio;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.utils;
+import it.reyboz.bustorino.util.RouteSorterByArrivalTime;
/**
* This once was a ListView Adapter for BusLine[].
@@ -60,7 +60,7 @@
private static final int tramIcon = R.drawable.tram;
private final String KEY_CAPITALIZE;
- private Capitalize capit = Capitalize.DO_NOTHING;
+ private Capitalize capit;
//private static final int cityIcon = R.drawable.city;
@@ -89,6 +89,25 @@
super(context, row_layout, p.queryAllRoutes());
li = LayoutInflater.from(context);
sort(new RouteSorterByArrivalTime());
+ /*
+ sort(new Comparator() {
+
+ @Override
+ public int compare(Route route, Route t1) {
+ LinesNameSorter sorter = new LinesNameSorter();
+ if(route.getNameForDisplay()!= null){
+ if(t1.getNameForDisplay()!=null){
+ return sorter.compare(route.getNameForDisplay(), t1.getNameForDisplay());
+ }
+ else return -1;
+ } else if(t1.getNameForDisplay()!=null){
+ return +1;
+ }
+ else return 0;
+ }
+ });
+
+ */
KEY_CAPITALIZE = context.getString(R.string.pref_arrival_times_capit);
SharedPreferences defSharPref = PreferenceManager.getDefaultSharedPreferences(context);
defSharPref.registerOnSharedPreferenceChangeListener(this);
diff --git a/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java b/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java
--- a/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java
+++ b/src/it/reyboz/bustorino/adapters/StopRecyclerAdapter.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Adapter components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.adapters;
import android.util.Log;
diff --git a/src/it/reyboz/bustorino/backend/Palina.java b/src/it/reyboz/bustorino/backend/Palina.java
--- a/src/it/reyboz/bustorino/backend/Palina.java
+++ b/src/it/reyboz/bustorino/backend/Palina.java
@@ -26,8 +26,11 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import it.reyboz.bustorino.util.LinesNameSorter;
+
/**
* Timetable for multiple routes.
*
@@ -91,83 +94,42 @@
* @return array index for this route
*/
public int addRoute(String routeID, String destinazione, Route.Type type) {
- this.routes.add(new Route(routeID, destinazione, type, new ArrayList<>(6)));
- routesModified = true;
- return this.routes.size() - 1; // last inserted element and pray that direct access to ArrayList elements really is direct
+ return addRoute(new Route(routeID, destinazione, type, new ArrayList<>(6)));
}
public int addRoute(Route r){
this.routes.add(r);
routesModified = true;
- return this.routes.size()-1;
+ buildRoutesString();
+ return this.routes.size()-1; // last inserted element and pray that direct access to ArrayList elements really is direct
}
+
public void setRoutes(List routeList){
routes = new ArrayList<>(routeList);
}
+ @Nullable
+ @Override
+ protected String buildRoutesString() {
+ // no routes => no string
+ if(routes == null || routes.size() == 0) {
+ return "";
+ }
+ final StringBuilder sb = new StringBuilder();
+ final LinesNameSorter nameSorter = new LinesNameSorter();
+ Collections.sort(routes, (o1, o2) -> nameSorter.compare(o1.getName().trim(), o2.getName().trim()));
+ int i, lenMinusOne = routes.size() - 1;
+
+ for (i = 0; i < lenMinusOne; i++) {
+ sb.append(routes.get(i).getName().trim()).append(", ");
+ }
+ // last one:
+ sb.append(routes.get(i).getName());
+
+ setRoutesThatStopHereString(sb.toString());
+ return routesThatStopHereToString();
+ }
-// /**
-// * Clears a route timetable (or creates an empty route) and returns its index
-// *
-// * @param routeID name
-// * @param destinazione end of line\terminus
-// * @return array index for this route
-// */
-// public int updateRoute(String routeID, String destinazione) {
-// int s = this.routes.size();
-// RouteInternal r;
-//
-// for(int i = 0; i < s; i++) {
-// r = routes.get(i);
-// if(r.name.compareTo(routeID) == 0 && r.destinazione.compareTo(destinazione) == 0) {
-// // capire se รจ possibile che ci siano stessa linea e stessa destinazione su 2 righe diverse del sito e qui una sovrascrive l'altra (probabilmente no)
-// r.updateFlag();
-// r.deletePassaggio();
-// return i;
-// }
-// }
-//
-// return this.addRoute(routeID, destinazione);
-// }
-//
-// /**
-// * Deletes routes marked as "not updated" (= disappeared from the GTT website\API\whatever).
-// * Sets all remaining routes to "not updated" because that's how this contraption works.
-// */
-// public void finishUpdatingRoutes() {
-// RouteInternal r;
-//
-// for(Iterator itr = this.routes.iterator(); itr.hasNext(); ) {
-// r = itr.next();
-// if(r.unupdateFlag()) {
-// itr.remove();
-// }
-// }
-// }
-// /**
-// * Gets the current timetable for a route. Returns null if the route doesn't exist.
-// * This is slower than queryRouteByIndex.
-// *
-// * @return timetable (passaggi)
-// */
-// public List queryRoute(String routeID) {
-// for(Route r : this.routes) {
-// if(routeID.equals(r.name)) {
-// return r.getPassaggi();
-// }
-// }
-//
-// return null;
-// }
-//
-// /**
-// * Gets the current timetable for this route, from its index in the array.
-// *
-// * @return timetable (passaggi)
-// */
-// public List queryRouteByIndex(int index) {
-// return this.routes.get(index).getPassaggi();
-// }
protected void checkPassaggi(){
Passaggio.Source mSource = null;
for (Route r: routes){
@@ -222,6 +184,7 @@
public int addInfoFromRoutes(List additionalRoutes){
if(routes == null || routes.size()==0) {
this.routes = new ArrayList<>(additionalRoutes);
+ buildRoutesString();
return routes.size();
}
int count=0;
@@ -280,6 +243,7 @@
//MERGE INFO
if(r.mergeRouteWithAnother(selected)) count++;
}
+ if (count> 0) buildRoutesString();
return count;
}
diff --git a/src/it/reyboz/bustorino/backend/Stop.java b/src/it/reyboz/bustorino/backend/Stop.java
--- a/src/it/reyboz/bustorino/backend/Stop.java
+++ b/src/it/reyboz/bustorino/backend/Stop.java
@@ -115,12 +115,16 @@
this.routesThatStopHere = routesThatStopHere;
}
+ protected void setRoutesThatStopHereString(String routesStopping){
+ this.routesThatStopHereString = routesStopping;
+ }
+
@Nullable
protected List getRoutesThatStopHere(){
return routesThatStopHere;
}
- private @Nullable String buildRoutesString() {
+ protected @Nullable String buildRoutesString() {
// no routes => no string
if(this.routesThatStopHere == null || this.routesThatStopHere.size() == 0) {
return null;
diff --git a/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java b/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java
--- a/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java
+++ b/src/it/reyboz/bustorino/backend/gtfs/GtfsDataParser.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Backend components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.backend.gtfs;
import android.content.Context;
@@ -162,7 +179,7 @@
stream.close();
}
- public static void readCSVWithColumns(BufferedReader reader, String tableName, Context con) throws IOException {
+ public static void readCSVWithColumns(BufferedReader reader, String tableName, Context con) {
//String[] elements;
List lineElements;
@@ -255,7 +272,7 @@
public static List readCsvLine(String line) throws IllegalArgumentException
{
- List list = new ArrayList();
+ List list = new ArrayList<>();
line += ",";
for (int x = 0; x < line.length(); x++)
diff --git a/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java b/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java
--- a/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java
+++ b/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java
@@ -1,3 +1,20 @@
+/*
+ BusTO - Backend components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.backend.mato;
import android.util.Log;
@@ -52,7 +69,7 @@
data.put("variables", variables);
- data.put("query", MatoAPIFetcher.QUERY_ARRIVALS);
+ data.put("query", MatoQueries.QUERY_ARRIVALS);
} catch (JSONException e) {
e.printStackTrace();
throw new AuthFailureError("Error with JSON enconding",e);
@@ -99,11 +116,4 @@
}
return Response.success(p, HttpHeaderParser.parseCacheHeaders(response));
}
-
-
- @Nullable
- @Override
- protected Map getParams() throws AuthFailureError {
- return new HashMap<>();
- }
}
diff --git a/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java b/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java
--- a/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java
+++ b/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java
@@ -24,10 +24,6 @@
}
- @Nullable
- @Override
- abstract protected Map getParams() throws AuthFailureError;
-
@Override
protected void deliverResponse(T response) {
listener.onResponse(response);
@@ -37,4 +33,5 @@
public Map getHeaders() throws AuthFailureError {
return MatoAPIFetcher.Companion.getREQ_PARAMETERS();
}
+
}
diff --git a/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt b/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
--- a/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
+++ b/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
@@ -1,3 +1,20 @@
+/*
+ BusTO - Backend components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
package it.reyboz.bustorino.backend.mato
import android.content.Context
@@ -15,21 +32,23 @@
-open class MatoAPIFetcher : ArrivalsFetcher {
+open class MatoAPIFetcher(val minNumPassaggi: Int) : ArrivalsFetcher {
var appContext: Context? = null
set(value) {
field = value!!.applicationContext
}
+ constructor(): this(3)
+
override fun ReadArrivalTimesAll(stopID: String?, res: AtomicReference?): Palina {
stopID!!
val future = RequestFuture.newFuture()
- val now = Calendar.getInstance().time;
- var numMinutes = 30;
+ val now = Calendar.getInstance().time
+ var numMinutes = 30
var palina = Palina(stopID)
var numPassaggi = 0
var trials = 0
- while (numPassaggi < 2 && trials < 4) {
+ while (numPassaggi < minNumPassaggi && trials < 4) {
numMinutes += 15
val request = MapiArrivalRequest(stopID, now, numMinutes * 60, 10, future, future)
@@ -38,10 +57,9 @@
return Palina(stopID)
}
val requestQueue = NetworkVolleyManager.getInstance(appContext).requestQueue
- request.setTag(VOLLEY_TAG)
+ request.setTag(getVolleyReqTag(QueryType.ARRIVALS))
requestQueue.add(request)
-
try {
val palinaResult = future.get(5, TimeUnit.SECONDS)
if (palinaResult!=null) {
@@ -84,6 +102,44 @@
"DNT" to "1",
"Host" to "mapi.5t.torino.it")
+ fun getVolleyReqTag(type: QueryType): String{
+ return when (type){
+ QueryType.ALL_STOPS -> VOLLEY_TAG +"_AllStops"
+ QueryType.ARRIVALS -> VOLLEY_TAG+"_Arrivals"
+ }
+ }
+
+ /**
+ * Get stops from the MatoAPI, set [res] accordingly
+ */
+ fun getAllStopsGTT(context: Context, res: AtomicReference?): List{
+ val requestQueue = NetworkVolleyManager.getInstance(context).requestQueue
+ val future = RequestFuture.newFuture>()
+
+ val request = VolleyAllStopsRequest(future, future)
+ request.tag = getVolleyReqTag(QueryType.ALL_STOPS)
+
+ requestQueue.add(request)
+
+ var palinaList:List = mutableListOf()
+
+ try {
+ palinaList = future.get(30, TimeUnit.SECONDS)
+
+ res?.set(Fetcher.Result.OK)
+ }catch (e: InterruptedException) {
+ e.printStackTrace()
+ res?.set(Fetcher.Result.PARSER_ERROR)
+ } catch (e: ExecutionException) {
+ e.printStackTrace()
+ res?.set(Fetcher.Result.SERVER_ERROR)
+ } catch (e: TimeoutException) {
+ res?.set(Fetcher.Result.CONNECTION_ERROR)
+ e.printStackTrace()
+ }
+ return palinaList
+ }
+ /*
fun makeRequest(type: QueryType?, variables: JSONObject) : String{
type.let {
val requestData = JSONObject()
@@ -91,7 +147,7 @@
QueryType.ARRIVALS ->{
requestData.put("operationName","AllStopsDirect")
requestData.put("variables", variables)
- requestData.put("query", QUERY_ARRIVALS)
+ requestData.put("query", MatoQueries.QUERY_ARRIVALS)
}
else -> {
//TODO all other cases
@@ -106,6 +162,7 @@
}
return ""
}
+ */
fun parseStopJSON(jsonStop: JSONObject): Palina{
val latitude = jsonStop.getDouble("lat")
val longitude = jsonStop.getDouble("lon")
@@ -118,6 +175,7 @@
val routesStoppingJSON = jsonStop.getJSONArray("routes")
val baseRoutes = mutableListOf()
+ // get all the possible routes
for (i in 0 until routesStoppingJSON.length()){
val routeBaseInfo = routesStoppingJSON.getJSONObject(i)
val r = Route(routeBaseInfo.getString("shortName"), Route.Type.UNKNOWN,"")
@@ -125,20 +183,26 @@
baseRoutes.add(r)
}
-
- val routesStopTimes = jsonStop.getJSONArray("stoptimesForPatterns")
-
- for (i in 0 until routesStopTimes.length()){
- val patternJSON = routesStopTimes.getJSONObject(i)
- val mRoute = parseRouteStoptimesJSON(patternJSON)
-
- //val directionId = patternJSON.getJSONObject("pattern").getInt("directionId")
- //TODO: use directionId
- palina.addRoute(mRoute)
- for (r in baseRoutes) {
- if (palina.gtfsID != null && r.gtfsId.equals(palina.gtfsID)) {
- baseRoutes.remove(r)
- break
+ if (jsonStop.has("desc")){
+ palina.location = jsonStop.getString("desc")
+ }
+ //there is also "zoneId" which is the zone of the stop (0-> city, etc)
+
+ if(jsonStop.has("stoptimesForPatterns")) {
+ val routesStopTimes = jsonStop.getJSONArray("stoptimesForPatterns")
+
+ for (i in 0 until routesStopTimes.length()) {
+ val patternJSON = routesStopTimes.getJSONObject(i)
+ val mRoute = parseRouteStoptimesJSON(patternJSON)
+
+ //val directionId = patternJSON.getJSONObject("pattern").getInt("directionId")
+ //TODO: use directionId
+ palina.addRoute(mRoute)
+ for (r in baseRoutes) {
+ if (palina.gtfsID != null && r.gtfsId.equals(palina.gtfsID)) {
+ baseRoutes.remove(r)
+ break
+ }
}
}
}
@@ -146,13 +210,11 @@
palina.addRoute(noArrivalRoute)
}
//val gtfsRoutes = mutableListOf<>()
-
-
return palina
}
fun parseRouteStoptimesJSON(jsonPatternWithStops: JSONObject): Route{
val patternJSON = jsonPatternWithStops.getJSONObject("pattern")
- val routeJSON = patternJSON.getJSONObject("route");
+ val routeJSON = patternJSON.getJSONObject("route")
val passaggiJSON = jsonPatternWithStops.getJSONArray("stoptimes")
val gtfsId = routeJSON.getString("gtfsId").trim()
@@ -184,59 +246,19 @@
return route
}
- const val QUERY_ARRIVALS="""query AllStopsDirect(
- ${'$'}name: String
- ${'$'}startTime: Long
- ${'$'}timeRange: Int
- ${'$'}numberOfDepartures: Int
- ) {
- stops(name: ${'$'}name) {
- __typename
- lat
- lon
- gtfsId
- code
- name
- desc
- wheelchairBoarding
- routes {
- __typename
- gtfsId
- shortName
- }
- stoptimesForPatterns(
- startTime: ${'$'}startTime
- timeRange: ${'$'}timeRange
- numberOfDepartures: ${'$'}numberOfDepartures
- ) {
- __typename
- pattern {
- __typename
- headsign
- directionId
- route {
- __typename
- gtfsId
- shortName
- mode
- }
- }
- stoptimes {
- __typename
- scheduledArrival
- realtimeArrival
- realtime
- realtimeState
- }
- }
- }
- }
- """
- }
+ fun makeRequestParameters(requestName:String, variables: JSONObject, query: String): JSONObject{
+ val data = JSONObject()
+ data.put("operationName", requestName)
+ data.put("variables", variables)
+ data.put("query", query)
+ return data
+ }
+
+ }
enum class QueryType {
- ARRIVALS,
+ ARRIVALS, ALL_STOPS
}
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/backend/mato/MatoQueries.kt b/src/it/reyboz/bustorino/backend/mato/MatoQueries.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/backend/mato/MatoQueries.kt
@@ -0,0 +1,90 @@
+/*
+ BusTO - Backend components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.backend.mato
+
+class MatoQueries {
+
+ companion object{
+ const val QUERY_ARRIVALS="""query AllStopsDirect(
+ ${'$'}name: String
+ ${'$'}startTime: Long
+ ${'$'}timeRange: Int
+ ${'$'}numberOfDepartures: Int
+ ) {
+ stops(name: ${'$'}name) {
+ __typename
+ lat
+ lon
+ gtfsId
+ code
+ name
+ desc
+ wheelchairBoarding
+ routes {
+ __typename
+ gtfsId
+ shortName
+ }
+ stoptimesForPatterns(
+ startTime: ${'$'}startTime
+ timeRange: ${'$'}timeRange
+ numberOfDepartures: ${'$'}numberOfDepartures
+ ) {
+ __typename
+ pattern {
+ __typename
+ headsign
+ directionId
+ route {
+ __typename
+ gtfsId
+ shortName
+ mode
+ }
+ }
+ stoptimes {
+ __typename
+ scheduledArrival
+ realtimeArrival
+ realtime
+ realtimeState
+ }
+ }
+ }
+ }
+ """
+
+ const val ALL_STOPS_BY_FEEDS="""
+ query AllStops(${'$'}feeds: [String!]){
+ stops(feeds: ${'$'}feeds) {
+
+ lat
+ lon
+ gtfsId
+ code
+ name
+ desc
+ routes {
+ gtfsId
+ shortName
+ }
+ }
+ }
+ """
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/backend/mato/VolleyAllStopsRequest.kt b/src/it/reyboz/bustorino/backend/mato/VolleyAllStopsRequest.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/backend/mato/VolleyAllStopsRequest.kt
@@ -0,0 +1,79 @@
+/*
+ BusTO - Backend components
+ Copyright (C) 2021 Fabio Mazza
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+package it.reyboz.bustorino.backend.mato
+
+import android.util.Log
+import com.android.volley.NetworkResponse
+import com.android.volley.Response
+import com.android.volley.VolleyError
+import com.android.volley.toolbox.HttpHeaderParser
+import it.reyboz.bustorino.backend.Palina
+import org.json.JSONArray
+import org.json.JSONException
+import org.json.JSONObject
+
+class VolleyAllStopsRequest(
+ listener: Response.Listener>,
+ errorListener: Response.ErrorListener,
+) : MapiVolleyRequest>(
+ MatoAPIFetcher.QueryType.ALL_STOPS,listener, errorListener) {
+ private val FEEDS = JSONArray()
+ init {
+
+ FEEDS.put("gtt")
+ }
+ override fun getBody(): ByteArray {
+ val variables = JSONObject()
+ variables.put("feeds", FEEDS)
+
+ val data = MatoAPIFetcher.makeRequestParameters("AllStops", variables, MatoQueries.ALL_STOPS_BY_FEEDS)
+
+ return data.toString().toByteArray()
+ }
+
+ override fun parseNetworkResponse(response: NetworkResponse?): Response> {
+ if (response==null)
+ return Response.error(VolleyError("Null response"))
+ else if(response.statusCode != 200)
+ return Response.error(VolleyError("Response not ready, status "+response.statusCode))
+
+ val stringResponse = String(response.data)
+ val palinas = ArrayList()
+
+ try {
+ val allData = JSONObject(stringResponse).getJSONObject("data")
+ val allStops = allData.getJSONArray("stops")
+
+ for (i in 0 until allStops.length()){
+ val jsonStop = allStops.getJSONObject(i)
+ palinas.add(MatoAPIFetcher.parseStopJSON(jsonStop))
+ }
+
+ } catch (e: JSONException){
+ Log.e("VolleyBusTO","Cannot parse response as JSON")
+ e.printStackTrace()
+ return Response.error(VolleyError("Error parsing JSON"))
+
+ }
+ return Response.success(palinas, HttpHeaderParser.parseCacheHeaders(response))
+ }
+ companion object{
+ val FEEDS_STR = arrayOf("gtt")
+
+ }
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/data/DBUpdateWorker.java b/src/it/reyboz/bustorino/data/DBUpdateWorker.java
--- a/src/it/reyboz/bustorino/data/DBUpdateWorker.java
+++ b/src/it/reyboz/bustorino/data/DBUpdateWorker.java
@@ -53,6 +53,8 @@
public static final String DEBUG_TAG = "Busto-UpdateWorker";
+ private static final long UPDATE_MIN_DELAY= 3*7*24*3600; //3 weeks
+
public DBUpdateWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
@@ -72,9 +74,14 @@
final boolean isUpdateCompulsory = getInputData().getBoolean(FORCED_UPDATE,false);
+ final long lastDBUpdateTime = shPr.getLong(DatabaseUpdate.DB_LAST_UPDATE_KEY, 0);
+ long currentTime = System.currentTimeMillis()/1000;
+
final int notificationID = showNotification();
Log.d(DEBUG_TAG, "Have previous version: "+current_DB_version +" and new version "+new_DB_version);
Log.d(DEBUG_TAG, "Update compulsory: "+isUpdateCompulsory);
+ /*
+ SKIP CHECK (Reason: The Old API might fail at any moment)
if (new_DB_version < 0){
//there has been an error
final Data out = new Data.Builder().putInt(ERROR_REASON_KEY, ERROR_FETCHING_VERSION)
@@ -82,9 +89,11 @@
cancelNotification(notificationID);
return ListenableWorker.Result.failure(out);
}
+ */
//we got a good version
- if (current_DB_version >= new_DB_version && !isUpdateCompulsory) {
+ if (!(current_DB_version < new_DB_version || currentTime > lastDBUpdateTime + UPDATE_MIN_DELAY )
+ && !isUpdateCompulsory) {
//don't need to update
cancelNotification(notificationID);
return ListenableWorker.Result.success(new Data.Builder().
@@ -115,6 +124,8 @@
//update the version in the shared preference
final SharedPreferences.Editor editor = shPr.edit();
editor.putInt(DatabaseUpdate.DB_VERSION_KEY, new_DB_version);
+ currentTime = System.currentTimeMillis()/1000;
+ editor.putLong(DatabaseUpdate.DB_LAST_UPDATE_KEY, currentTime);
editor.apply();
cancelNotification(notificationID);
diff --git a/src/it/reyboz/bustorino/data/DatabaseUpdate.java b/src/it/reyboz/bustorino/data/DatabaseUpdate.java
--- a/src/it/reyboz/bustorino/data/DatabaseUpdate.java
+++ b/src/it/reyboz/bustorino/data/DatabaseUpdate.java
@@ -27,12 +27,18 @@
import it.reyboz.bustorino.R;
import it.reyboz.bustorino.backend.Fetcher;
import it.reyboz.bustorino.backend.FiveTAPIFetcher;
+import it.reyboz.bustorino.backend.Palina;
import it.reyboz.bustorino.backend.Route;
import it.reyboz.bustorino.backend.Stop;
+import it.reyboz.bustorino.backend.mato.MatoAPIFetcher;
+
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -41,13 +47,15 @@
public class DatabaseUpdate {
- public static final String DEBUG_TAG = "BusTO-DBUpdate";
- public static final int VERSION_UNAVAILABLE = -2;
- public static final int JSON_PARSING_ERROR = -4;
+ public static final String DEBUG_TAG = "BusTO-DBUpdate";
+ public static final int VERSION_UNAVAILABLE = -2;
+ public static final int JSON_PARSING_ERROR = -4;
+
+ public static final String DB_VERSION_KEY = "NextGenDB.GTTVersion";
+ public static final String DB_LAST_UPDATE_KEY = "NextGenDB.LastDBUpdate";
- public static final String DB_VERSION_KEY = "NextGenDB.GTTVersion";
- enum Result {
+ enum Result {
DONE, ERROR_STOPS_DOWNLOAD, ERROR_LINES_DOWNLOAD
}
@@ -80,6 +88,7 @@
public static Result performDBUpdate(Context con, AtomicReference gres) {
final FiveTAPIFetcher f = new FiveTAPIFetcher();
+ /*
final ArrayList stops = f.getAllStopsFromGTT(gres);
//final ArrayList cpOp = new ArrayList<>();
@@ -88,9 +97,18 @@
return DatabaseUpdate.Result.ERROR_STOPS_DOWNLOAD;
}
- // return false; //If the commit to the SharedPreferences didn't succeed, simply stop updating the database
+
+ */
final NextGenDB dbHelp = new NextGenDB(con.getApplicationContext());
final SQLiteDatabase db = dbHelp.getWritableDatabase();
+
+ final List palinasMatoAPI = MatoAPIFetcher.Companion.getAllStopsGTT(con, gres);
+ if (gres.get() != Fetcher.Result.OK) {
+ Log.w(DEBUG_TAG, "Something went wrong downloading");
+ return DatabaseUpdate.Result.ERROR_STOPS_DOWNLOAD;
+
+ }
+ //TODO: Get the type of stop from the lines
//Empty the needed tables
db.beginTransaction();
//db.execSQL("DELETE FROM "+StopsTable.TABLE_NAME);
@@ -99,20 +117,20 @@
//put new data
long startTime = System.currentTimeMillis();
- Log.d(DEBUG_TAG, "Inserting " + stops.size() + " stops");
- for (final Stop s : stops) {
+ Log.d(DEBUG_TAG, "Inserting " + palinasMatoAPI.size() + " stops");
+ for (final Palina p : palinasMatoAPI) {
final ContentValues cv = new ContentValues();
- cv.put(NextGenDB.Contract.StopsTable.COL_ID, s.ID);
- cv.put(NextGenDB.Contract.StopsTable.COL_NAME, s.getStopDefaultName());
- if (s.location != null)
- cv.put(NextGenDB.Contract.StopsTable.COL_LOCATION, s.location);
- cv.put(NextGenDB.Contract.StopsTable.COL_LAT, s.getLatitude());
- cv.put(NextGenDB.Contract.StopsTable.COL_LONG, s.getLongitude());
- if (s.getAbsurdGTTPlaceName() != null) cv.put(NextGenDB.Contract.StopsTable.COL_PLACE, s.getAbsurdGTTPlaceName());
- cv.put(NextGenDB.Contract.StopsTable.COL_LINES_STOPPING, s.routesThatStopHereToString());
- if (s.type != null) cv.put(NextGenDB.Contract.StopsTable.COL_TYPE, s.type.getCode());
-
+ cv.put(NextGenDB.Contract.StopsTable.COL_ID, p.ID);
+ cv.put(NextGenDB.Contract.StopsTable.COL_NAME, p.getStopDefaultName());
+ if (p.location != null)
+ cv.put(NextGenDB.Contract.StopsTable.COL_LOCATION, p.location);
+ cv.put(NextGenDB.Contract.StopsTable.COL_LAT, p.getLatitude());
+ cv.put(NextGenDB.Contract.StopsTable.COL_LONG, p.getLongitude());
+ if (p.getAbsurdGTTPlaceName() != null) cv.put(NextGenDB.Contract.StopsTable.COL_PLACE, p.getAbsurdGTTPlaceName());
+ cv.put(NextGenDB.Contract.StopsTable.COL_LINES_STOPPING, p.routesThatStopHereToString());
+ if (p.type != null) cv.put(NextGenDB.Contract.StopsTable.COL_TYPE, p.type.getCode());
+ if (p.gtfsID != null) cv.put(NextGenDB.Contract.StopsTable.COL_GTFS_ID, p.gtfsID);
//Log.d(DEBUG_TAG,cv.toString());
//cpOp.add(ContentProviderOperation.newInsert(uritobeused).withValues(cv).build());
//valuesArr[i] = cv;
@@ -184,16 +202,23 @@
public static void requestDBUpdateWithWork(Context con, boolean forced){
final SharedPreferences theShPr = PreferencesHolder.getMainSharedPreferences(con);
final WorkManager workManager = WorkManager.getInstance(con);
- PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 1, TimeUnit.DAYS)
+ PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 7, TimeUnit.DAYS)
.setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES)
.setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
.build())
.build();
final int version = theShPr.getInt(DatabaseUpdate.DB_VERSION_KEY, -10);
- if (version >= 0 && !forced)
+ final long lastDBUpdateTime = theShPr.getLong(DatabaseUpdate.DB_LAST_UPDATE_KEY, -10);
+ if ((version >= 0 || lastDBUpdateTime >=0) && !forced)
workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
ExistingPeriodicWorkPolicy.KEEP, wr);
else workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG,
ExistingPeriodicWorkPolicy.REPLACE, wr);
}
+ /*
+ public static boolean isDBUpdating(){
+ return false;
+ TODO
+ }
+ */
}
diff --git a/src/it/reyboz/bustorino/data/NextGenDB.java b/src/it/reyboz/bustorino/data/NextGenDB.java
--- a/src/it/reyboz/bustorino/data/NextGenDB.java
+++ b/src/it/reyboz/bustorino/data/NextGenDB.java
@@ -36,7 +36,7 @@
public class NextGenDB extends SQLiteOpenHelper{
public static final String DATABASE_NAME = "bustodatabase.db";
- public static final int DATABASE_VERSION = 2;
+ public static final int DATABASE_VERSION = 3;
public static final String DEBUG_TAG = "NextGenDB-BusTO";
//NO Singleton instance
//private static volatile NextGenDB instance = null;
@@ -67,6 +67,7 @@
private static final String SQL_CREATE_STOPS_TABLE="CREATE TABLE "+Contract.StopsTable.TABLE_NAME+" ("+
Contract.StopsTable.COL_ID+" TEXT PRIMARY KEY, "+ Contract.StopsTable.COL_TYPE+" INTEGER, "+Contract.StopsTable.COL_LAT+" REAL NOT NULL, "+
Contract.StopsTable.COL_LONG+" REAL NOT NULL, "+ Contract.StopsTable.COL_NAME+" TEXT NOT NULL, "+
+ StopsTable.COL_GTFS_ID+" TEXT, "+
Contract.StopsTable.COL_LOCATION+" TEXT, "+Contract.StopsTable.COL_PLACE+" TEXT, "+
Contract.StopsTable.COL_LINES_STOPPING +" TEXT )";
@@ -77,7 +78,7 @@
Contract.StopsTable.COL_LINES_STOPPING +" TEXT )";
public static final String[] QUERY_COLUMN_stops_all = {
- StopsTable.COL_ID, StopsTable.COL_NAME, StopsTable.COL_LOCATION,
+ StopsTable.COL_ID, StopsTable.COL_NAME, StopsTable.COL_GTFS_ID, StopsTable.COL_LOCATION,
StopsTable.COL_TYPE, StopsTable.COL_LAT, StopsTable.COL_LONG, StopsTable.COL_LINES_STOPPING};
public static final String QUERY_WHERE_LAT_AND_LNG_IN_RANGE = StopsTable.COL_LAT + " >= ? AND " +
@@ -125,6 +126,14 @@
DatabaseUpdate.requestDBUpdateWithWork(appContext, true);
}
+ if(oldVersion < 3 && newVersion == 3){
+ Log.d("BusTO-Database", "Running upgrades for version 3");
+ //add the new column
+ db.execSQL("ALTER TABLE "+StopsTable.TABLE_NAME+
+ " ADD COLUMN "+StopsTable.COL_GTFS_ID+" TEXT ");
+
+ // DatabaseUpdate.requestDBUpdateWithWork(appContext, true);
+ }
}
@Override
@@ -209,7 +218,9 @@
while(result.moveToNext()) {
final String stopID = result.getString(colID).trim();
- final Route.Type type = Route.getTypeFromSymbol(result.getString(colType));
+ final Route.Type type;
+ if(result.getString(colType) == null) type = Route.Type.BUS;
+ else type = Route.getTypeFromSymbol(result.getString(colType));
String lines = result.getString(colLines).trim();
String locationSometimesEmpty = result.getString(colLocation);
@@ -252,6 +263,10 @@
return success;
}
+ int updateLinesStoppingInStop(List stops){
+ return 0;
+ }
+
public static List splitLinesString(String linesStr){
return Arrays.asList(linesStr.split("\\s*,\\s*"));
}
@@ -330,19 +345,21 @@
public static final String COL_ID = "stopid"; //integer
public static final String COL_TYPE = "stop_type";
public static final String COL_NAME = "stop_name";
+ public static final String COL_GTFS_ID = "gtfs_id";
public static final String COL_LAT = "stop_latitude";
public static final String COL_LONG = "stop_longitude";
public static final String COL_LOCATION = "stop_location";
public static final String COL_PLACE = "stop_placeName";
public static final String COL_LINES_STOPPING = "stop_lines";
+
@Override
public String getTableName() {
return TABLE_NAME;
}
@Override
public String[] getFields() {
- return new String[]{COL_ID,COL_TYPE,COL_NAME,COL_LAT,COL_LONG,COL_LOCATION,COL_PLACE,COL_LINES_STOPPING};
+ return new String[]{COL_ID,COL_TYPE,COL_NAME,COL_GTFS_ID,COL_LAT,COL_LONG,COL_LOCATION,COL_PLACE,COL_LINES_STOPPING};
}
}
}
diff --git a/src/it/reyboz/bustorino/adapters/RouteSorterByArrivalTime.kt b/src/it/reyboz/bustorino/util/RouteSorterByArrivalTime.kt
rename from src/it/reyboz/bustorino/adapters/RouteSorterByArrivalTime.kt
rename to src/it/reyboz/bustorino/util/RouteSorterByArrivalTime.kt
--- a/src/it/reyboz/bustorino/adapters/RouteSorterByArrivalTime.kt
+++ b/src/it/reyboz/bustorino/util/RouteSorterByArrivalTime.kt
@@ -1,4 +1,4 @@
-package it.reyboz.bustorino.adapters
+package it.reyboz.bustorino.util
import it.reyboz.bustorino.backend.Route
@@ -7,9 +7,9 @@
override fun compare(route1: Route?, route2: Route?): Int {
if (route1 == null){
if(route2 == null) return 0
- else return 2;
+ else return 2
} else if (route2 == null){
- return -2;
+ return -2
}
val passaggi1 = route1.passaggi
val passaggi2 = route2.passaggi