Implemented Canteen Browser

This commit is contained in:
Caesar2011
2018-07-23 00:32:05 +02:00
parent 5cd5bc6a1a
commit e7089e7b79
20 changed files with 869 additions and 33 deletions

View File

@@ -25,6 +25,8 @@ import de.sebse.fuplanner.fragments.ModulesFragment;
import de.sebse.fuplanner.fragments.ScheduleFragment; import de.sebse.fuplanner.fragments.ScheduleFragment;
import de.sebse.fuplanner.fragments.StartupFragment; import de.sebse.fuplanner.fragments.StartupFragment;
import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment; import de.sebse.fuplanner.fragments.moddetails.ModDetailFragment;
import de.sebse.fuplanner.services.Canteen.CanteenBrowser;
import de.sebse.fuplanner.services.Canteen.types.Canteen;
import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth; import de.sebse.fuplanner.services.GoogleAuth.GoogleAuth;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.types.LoginToken; import de.sebse.fuplanner.services.KVV.types.LoginToken;
@@ -57,6 +59,7 @@ public class MainActivity extends AppCompatActivity
private int fragmentPage = FRAGMENT_NONE; private int fragmentPage = FRAGMENT_NONE;
private String fragmentData = ""; private String fragmentData = "";
private CanteenBrowser mCanteenBrowser;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@@ -97,6 +100,13 @@ public class MainActivity extends AppCompatActivity
else else
checkAndDoLogin(); checkAndDoLogin();
} }
this.getCanteenBrowser().getCanteens(success -> {
Canteen canteen = success.get(0);
this.getCanteenBrowser().getCanteen(canteen, success1 -> {
this.getCanteenBrowser().getDay(canteen.get(0), log::d, log::e, true);
}, log::e, true);
}, log::e, true);
} }
@Override @Override
@@ -204,6 +214,13 @@ public class MainActivity extends AppCompatActivity
return this.mKVV; return this.mKVV;
} }
public CanteenBrowser getCanteenBrowser() {
if (this.mCanteenBrowser == null) {
this.mCanteenBrowser = new CanteenBrowser(this);
}
return this.mCanteenBrowser;
}
private int getDefaultFragmentAfterLogin() { private int getDefaultFragmentAfterLogin() {
return FRAGMENT_MODULES; return FRAGMENT_MODULES;
} }
@@ -271,6 +288,17 @@ public class MainActivity extends AppCompatActivity
findViewById(R.id.app_bar_layout).setVisibility(View.GONE); findViewById(R.id.app_bar_layout).setVisibility(View.GONE);
} else { } else {
findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE); findViewById(R.id.app_bar_layout).setVisibility(View.VISIBLE);
getCanteenBrowser().getCanteens(success -> {
int i = 0;
for (Canteen module : success) {
MenuItem menuItem = mNavigationView.getMenu().add(Menu.NONE, Menu.NONE, 101 + i, module.getName());
menuItem.setOnMenuItemClickListener(item -> {
log.d("canteen click", module.getId());
return false;
});
i++;
}
}, log::e);
} }
// switch to logout // switch to logout
if ((fragmentPage != FRAGMENT_STARTUP && fragmentPage != FRAGMENT_LOGIN) && (newFragment == FRAGMENT_STARTUP || newFragment == FRAGMENT_LOGIN)) { if ((fragmentPage != FRAGMENT_STARTUP && fragmentPage != FRAGMENT_LOGIN) && (newFragment == FRAGMENT_STARTUP || newFragment == FRAGMENT_LOGIN)) {
@@ -298,8 +326,6 @@ public class MainActivity extends AppCompatActivity
mNavigationView.inflateMenu(R.menu.activity_main_drawer_login); mNavigationView.inflateMenu(R.menu.activity_main_drawer_login);
mNavigationView.setCheckedItem(R.id.nav_modules); mNavigationView.setCheckedItem(R.id.nav_modules);
getKVV().getModuleList(success -> { getKVV().getModuleList(success -> {
log.d("Modules.get", success.size());
//SubMenu moduleMenu = navigationView.getMenu().findItem(R.id.nav_modules).getSubMenu();
int i = 0; int i = 0;
for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) { for (Iterator<Modules.Module> it = success.latestSemesterIterator(); it.hasNext(); ) {
Modules.Module module = it.next(); Modules.Module module = it.next();
@@ -310,7 +336,7 @@ public class MainActivity extends AppCompatActivity
}); });
i++; i++;
} }
}, error -> log.e("Modules.error", error)); }, log::e);
} }
if (newFragment == FRAGMENT_MODULES_DETAILS) { if (newFragment == FRAGMENT_MODULES_DETAILS) {
getKVV().getModule(newData, success -> { getKVV().getModule(newData, success -> {

View File

@@ -18,7 +18,7 @@ import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.KVV; import de.sebse.fuplanner.services.KVV.KVV;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.KVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import de.sebse.fuplanner.tools.MainAcitivityListener; import de.sebse.fuplanner.tools.MainAcitivityListener;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.ui.weekview.MonthLoader; import de.sebse.fuplanner.tools.ui.weekview.MonthLoader;
@@ -143,6 +143,6 @@ public class ScheduleFragment extends Fragment implements MonthLoader.MonthChang
Calendar newLastVisibleDay = (Calendar) newFirstVisibleDay.clone(); Calendar newLastVisibleDay = (Calendar) newFirstVisibleDay.clone();
newLastVisibleDay.add(Calendar.HOUR, 24*mWeekView.getNumberOfVisibleDays()); newLastVisibleDay.add(Calendar.HOUR, 24*mWeekView.getNumberOfVisibleDays());
//mListener.onScheduleFragmentInteraction(newFirstVisibleDay, newLastVisibleDay); //mListener.onScheduleFragmentInteraction(newFirstVisibleDay, newLastVisibleDay);
mListener.onTitleTextChange(getResources().getString(R.string.date_scale, Conversion.getModifiedDate(newFirstVisibleDay.getTimeInMillis()), Conversion.getModifiedDate(newLastVisibleDay.getTimeInMillis()))); mListener.onTitleTextChange(getResources().getString(R.string.date_scale, DateUtils.getModifiedDate(newFirstVisibleDay.getTimeInMillis()), DateUtils.getModifiedDate(newLastVisibleDay.getTimeInMillis())));
} }
} }

View File

@@ -8,7 +8,7 @@ import android.widget.BaseExpandableListAdapter;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Announcement; import de.sebse.fuplanner.services.KVV.types.Announcement;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.StringViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder;
@@ -81,7 +81,7 @@ public class ModDetailAnnounceAdapter extends BaseExpandableListAdapter {
ItemViewHolder itemHolder = new ItemViewHolder(convertView); ItemViewHolder itemHolder = new ItemViewHolder(convertView);
itemHolder.mTitle.setText(announce.getTitle()); itemHolder.mTitle.setText(announce.getTitle());
itemHolder.mSubLeft.setText(announce.getCreatedBy()); itemHolder.mSubLeft.setText(announce.getCreatedBy());
itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(parent.getContext(), announce.getCreatedOn())); itemHolder.mSubRight.setText(DateUtils.getModifiedDateTime(parent.getContext(), announce.getCreatedOn()));
return convertView; return convertView;
} }

View File

@@ -8,7 +8,7 @@ import android.widget.BaseExpandableListAdapter;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Assignment; import de.sebse.fuplanner.services.KVV.types.Assignment;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder;
import de.sebse.fuplanner.tools.ui.StringViewHolder; import de.sebse.fuplanner.tools.ui.StringViewHolder;
@@ -92,7 +92,7 @@ public class ModDetailAssignmentAdapter extends BaseExpandableListAdapter {
itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.open)); itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.open));
else else
itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.close)); itemHolder.mSubLeft.setText(itemHolder.mView.getResources().getText(R.string.close));
itemHolder.mSubRight.setText(Conversion.getModifiedDateTime(parent.getContext(), assignment.getDueDate())); itemHolder.mSubRight.setText(DateUtils.getModifiedDateTime(parent.getContext(), assignment.getDueDate()));
return convertView; return convertView;
} }

View File

@@ -13,7 +13,7 @@ import java.util.ArrayList;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.KVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.CustomViewHolder;
import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder;
@@ -114,14 +114,14 @@ public class ModDetailEventAdapter extends RecyclerView.Adapter<RecyclerView.Vie
i.mTitle.setText(event.getTitle()); i.mTitle.setText(event.getTitle());
i.mSubLeft.setText(event.getType()); i.mSubLeft.setText(event.getType());
String start, end; String start, end;
if (Conversion.dateEquals(event.getStartDate(), System.currentTimeMillis())) if (DateUtils.dateEquals(event.getStartDate(), System.currentTimeMillis()))
start = Conversion.getModifiedTime(i.mView.getContext(), event.getStartDate()); start = DateUtils.getModifiedTime(i.mView.getContext(), event.getStartDate());
else else
start = Conversion.getModifiedDateTime(i.mView.getContext(), event.getStartDate()); start = DateUtils.getModifiedDateTime(i.mView.getContext(), event.getStartDate());
if (Conversion.dateEquals(event.getStartDate(), event.getEndDate())) if (DateUtils.dateEquals(event.getStartDate(), event.getEndDate()))
end = Conversion.getModifiedTime(i.mView.getContext(), event.getEndDate()); end = DateUtils.getModifiedTime(i.mView.getContext(), event.getEndDate());
else else
end = Conversion.getModifiedDateTime(i.mView.getContext(), event.getEndDate()); end = DateUtils.getModifiedDateTime(i.mView.getContext(), event.getEndDate());
i.mSubRight.setText(i.mView.getResources().getString(R.string.date_scale, i.mSubRight.setText(i.mView.getResources().getString(R.string.date_scale,
start, end start, end
)); ));

View File

@@ -17,7 +17,7 @@ import de.sebse.fuplanner.services.KVV.types.Announcement;
import de.sebse.fuplanner.services.KVV.types.Assignment; import de.sebse.fuplanner.services.KVV.types.Assignment;
import de.sebse.fuplanner.services.KVV.types.Event; import de.sebse.fuplanner.services.KVV.types.Event;
import de.sebse.fuplanner.services.KVV.types.Modules; import de.sebse.fuplanner.services.KVV.types.Modules;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import de.sebse.fuplanner.tools.logging.Logger; import de.sebse.fuplanner.tools.logging.Logger;
import de.sebse.fuplanner.tools.ui.CustomViewHolder; import de.sebse.fuplanner.tools.ui.CustomViewHolder;
import de.sebse.fuplanner.tools.ui.ItemViewHolder; import de.sebse.fuplanner.tools.ui.ItemViewHolder;
@@ -142,7 +142,7 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
Announcement announce = mValue.announcements.get(index); Announcement announce = mValue.announcements.get(index);
i.mTitle.setText(announce.getTitle()); i.mTitle.setText(announce.getTitle());
i.mSubLeft.setText(announce.getCreatedBy()); i.mSubLeft.setText(announce.getCreatedBy());
i.mSubRight.setText(Conversion.getModifiedDateTime(i.mView.getContext(), announce.getCreatedOn())); i.mSubRight.setText(DateUtils.getModifiedDateTime(i.mView.getContext(), announce.getCreatedOn()));
i.mView.setOnClickListener(view -> log.d("Reference to:", SECTION_ANNOUNCEMENT, index)); i.mView.setOnClickListener(view -> log.d("Reference to:", SECTION_ANNOUNCEMENT, index));
break; break;
case SECTION_ASSIGNMENT: case SECTION_ASSIGNMENT:
@@ -152,7 +152,7 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
i.mSubLeft.setText(i.mView.getResources().getText(R.string.open)); i.mSubLeft.setText(i.mView.getResources().getText(R.string.open));
else else
i.mSubLeft.setText(i.mView.getResources().getText(R.string.close)); i.mSubLeft.setText(i.mView.getResources().getText(R.string.close));
i.mSubRight.setText(Conversion.getModifiedDateTime(i.mView.getContext(), assignment.getDueDate())); i.mSubRight.setText(DateUtils.getModifiedDateTime(i.mView.getContext(), assignment.getDueDate()));
i.mView.setOnClickListener(view -> log.d("Reference to:", SECTION_ASSIGNMENT, index)); i.mView.setOnClickListener(view -> log.d("Reference to:", SECTION_ASSIGNMENT, index));
break; break;
case SECTION_EVENTS: case SECTION_EVENTS:
@@ -160,14 +160,14 @@ public class ModDetailOverviewAdapter extends RecyclerView.Adapter<RecyclerView.
i.mTitle.setText(event.getTitle()); i.mTitle.setText(event.getTitle());
i.mSubLeft.setText(event.getType()); i.mSubLeft.setText(event.getType());
String start, end; String start, end;
if (Conversion.dateEquals(event.getStartDate(), System.currentTimeMillis())) if (DateUtils.dateEquals(event.getStartDate(), System.currentTimeMillis()))
start = Conversion.getModifiedTime(i.mView.getContext(), event.getStartDate()); start = DateUtils.getModifiedTime(i.mView.getContext(), event.getStartDate());
else else
start = Conversion.getModifiedDateTime(i.mView.getContext(), event.getStartDate()); start = DateUtils.getModifiedDateTime(i.mView.getContext(), event.getStartDate());
if (Conversion.dateEquals(event.getStartDate(), event.getEndDate())) if (DateUtils.dateEquals(event.getStartDate(), event.getEndDate()))
end = Conversion.getModifiedTime(i.mView.getContext(), event.getEndDate()); end = DateUtils.getModifiedTime(i.mView.getContext(), event.getEndDate());
else else
end = Conversion.getModifiedDateTime(i.mView.getContext(), event.getEndDate()); end = DateUtils.getModifiedDateTime(i.mView.getContext(), event.getEndDate());
i.mSubRight.setText(i.mView.getResources().getString(R.string.date_scale, i.mSubRight.setText(i.mView.getResources().getString(R.string.date_scale,
start, end start, end
)); ));

View File

@@ -0,0 +1,217 @@
package de.sebse.fuplanner.services.Canteen;
import android.content.Context;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import de.sebse.fuplanner.services.Canteen.types.Canteen;
import de.sebse.fuplanner.services.Canteen.types.Canteens;
import de.sebse.fuplanner.services.Canteen.types.Day;
import de.sebse.fuplanner.tools.AsyncQueue;
import de.sebse.fuplanner.tools.network.HTTPService;
import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkError;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;
public class CanteenBrowser extends HTTPService {
private Canteens canteens;
private AsyncQueue queue = new AsyncQueue();
private Context context;
public CanteenBrowser(Context context) {
super(context);
this.context = context;
try {
this.canteens = Canteens.load(context);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public void getCanteens(final NetworkCallback<Canteens> callback, final NetworkErrorCallback errorCallback) {
getCanteens(callback, errorCallback, false);
}
public void getCanteens(final NetworkCallback<Canteens> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
queue.add("list", () -> {
if (this.canteens != null && !forceRefresh) {
callback.onResponse(this.canteens);
queue.next("list");
return;
}
this.upgradeCanteens(success -> {
if (this.canteens == null)
this.canteens = success;
else
this.canteens.update(success);
this.save();
callback.onResponse(this.canteens);
queue.next("list");
}, queue.check("list", errorCallback));
});
}
private void upgradeCanteens(final NetworkCallback<Canteens> callback, final NetworkErrorCallback errorCallback) {
get("https://openmensa.org/api/v2/canteens", null, response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(201101, 403, "No canteen list retrieved!"));
return;
}
Canteens canteens = new Canteens();
try {
JSONArray json = new JSONArray(body);
for (int i = 0; i < json.length(); i++) {
JSONObject canteen = json.getJSONObject(i);
int id = canteen.getInt("id");
String name = canteen.getString("name");
String city = canteen.getString("city");
String address = canteen.getString("address");
JSONArray coords = canteen.getJSONArray("coordinates");
double lat = 0;
double lng = 0;
if (coords != null) {
lat = coords.getDouble(0);
lng = coords.getDouble(1);
}
for (int cant : Canteens.availableCanteens) {
if (cant == id) {
canteens.addCanteen(id, name, city, address, lat, lng);
break;
}
}
}
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(201102, 403, "Cannot parse canteen list!"));
return;
}
callback.onResponse(canteens);
}, error -> errorCallback.onError(new NetworkError(201103, error.networkResponse.statusCode, "Cannot get canteen list!")));
}
public void getCanteen(Canteen canteen, final NetworkCallback<Canteen> callback, final NetworkErrorCallback errorCallback) {
getCanteen(canteen, callback, errorCallback, false);
}
public void getCanteen(Canteen canteen, final NetworkCallback<Canteen> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
String hash = "canteen" + canteen.getId();
queue.add(hash, () -> {
log.d("getCanteen", canteen.size() > 0 && !forceRefresh);
if (canteen.size() > 0 && !forceRefresh) {
callback.onResponse(canteen);
queue.next(hash);
return;
}
this.upgradeCanteen(canteen, success -> {
canteen.update(success);
this.save();
callback.onResponse(canteen);
queue.next(hash);
}, queue.check(hash, errorCallback));
});
}
private void upgradeCanteen(Canteen canteen, final NetworkCallback<Canteen> callback, final NetworkErrorCallback errorCallback) {
get(String.format("https://openmensa.org/api/v2/canteens/%s/days", canteen.getId()), null, response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(201201, 403, "No day list retrieved!"));
return;
}
try {
JSONArray json = new JSONArray(body);
for (int i = 0; i < json.length(); i++) {
JSONObject day = json.getJSONObject(i);
String date = day.getString("date");
boolean closed = day.getBoolean("closed");
canteen.addDay(Canteen.keyToCalendar(date), closed);
}
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(201202, 403, "Cannot parse day list!"));
return;
}
callback.onResponse(canteen);
}, error -> errorCallback.onError(new NetworkError(201203, error.networkResponse.statusCode, "Cannot get day list!")));
}
public void getDay(Day day, final NetworkCallback<Day> callback, final NetworkErrorCallback errorCallback) {
getDay(day, callback, errorCallback, false);
}
public void getDay(Day day, final NetworkCallback<Day> callback, final NetworkErrorCallback errorCallback, boolean forceRefresh) {
String hash = "day" + day.getCanteenId() + "@@@" + Canteen.calendarToKey(day.getCalendar());
queue.add(hash, () -> {
if (day.size() > 0 && !forceRefresh) {
callback.onResponse(day);
queue.next(hash);
return;
}
this.upgradeDay(day, success -> {
day.update(success);
this.save();
callback.onResponse(day);
queue.next(hash);
}, queue.check(hash, errorCallback));
});
}
private void upgradeDay(Day day, final NetworkCallback<Day> callback, final NetworkErrorCallback errorCallback) {
get(String.format("https://openmensa.org/api/v2/canteens/%s/days/%s/meals/", day.getCanteenId(), Canteen.calendarToKey(day.getCalendar())), null, response -> {
String body = response.getParsed();
if (body == null) {
errorCallback.onError(new NetworkError(201301, 403, "No meal list retrieved!"));
return;
}
try {
JSONArray json = new JSONArray(body);
for (int i = 0; i < json.length(); i++) {
JSONObject meal = json.getJSONObject(i);
int id = meal.getInt("id");
String name = meal.getString("name");
String category = meal.getString("category");
JSONObject prices = meal.getJSONObject("prices");
double priceStdnt = 0;
double priceEmply = 0;
double priceOther = 0;
if (prices != null) {
priceStdnt = prices.getDouble("students");
priceEmply = prices.getDouble("employees");
priceOther = prices.getDouble("others");
}
JSONArray noteArray = meal.getJSONArray("notes");
String[] notes = new String[noteArray.length()];
for (int j = 0; j < noteArray.length(); j++) {
notes[j] = noteArray.getString(j);
}
day.addMeal(id, name, category, priceStdnt, priceEmply, priceOther, notes);
}
} catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(201302, 403, "Cannot parse meal list!"));
return;
}
callback.onResponse(day);
}, error -> errorCallback.onError(new NetworkError(201303, error.networkResponse.statusCode, "Cannot get meal list!")));
}
private void save() {
try {
this.canteens.save(this.context);
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,122 @@
package de.sebse.fuplanner.services.Canteen.types;
import android.support.annotation.NonNull;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;
import de.sebse.fuplanner.tools.SortedListDay;
public class Canteen implements Serializable, Iterable<Day> {
private final int id;
private final String name;
private final String city;
private final String address;
private final double lat;
private final double lng;
private SortedListDay list = new SortedListDay();
Canteen(int id, String name, String city, String address, double lat, double lng) {
this.id = id;
this.name = name;
this.city = city;
this.address = address;
this.lat = lat;
this.lng = lng;
}
private Day getDay(Calendar calendar) {
return this.list.getById(calendar);
}
public void addDay(Calendar calendar, boolean isClosed) {
Day day = new Day(this, calendar, isClosed);
addDay(day);
}
private void addDay(@NonNull Day day) {
if (!day.isClosed()) {
this.list.add(day);
}
Calendar minDate = Calendar.getInstance();
minDate.add(Calendar.DAY_OF_YEAR, -1);
Calendar maxDate = Calendar.getInstance();
maxDate.add(Calendar.DAY_OF_YEAR, 14);
for (int i = this.list.size() - 1; i >= 0; i--) {
Day d = this.list.get(i);
if (d != null && (d.getCalendar().before(minDate) || d.getCalendar().after(maxDate)))
this.list.remove(i);
}
}
public int size() {
return this.list.size();
}
public Day get(int index) {
return this.list.get(index);
}
public void update(Canteen canteen) {
SortedListDay oldList = this.list;
this.list = canteen.list;
for (Day oldDay: oldList) {
Day newDay = getDay(oldDay.getCalendar());
if (newDay != null) newDay.update(oldDay);
}
}
@NonNull
@Override
public Iterator<Day> iterator() {
return this.list.iterator();
}
public static String calendarToKey(Calendar calendar) {
int y = calendar.get(Calendar.YEAR);
int m = calendar.get(Calendar.MONTH)+1;
int d = calendar.get(Calendar.DAY_OF_MONTH);
return String.format(Locale.getDefault(), "%d-%d-%d", y, m, d);
}
public static Calendar keyToCalendar(String dateString) {
int y = Integer.parseInt(dateString.substring(0, 4));
int m = Integer.parseInt(dateString.substring(5, 7))-1;
int d = Integer.parseInt(dateString.substring(8, 10));
Calendar cal = Calendar.getInstance();
cal.set(y, m, d, 0, 0, 0);
return cal;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getCity() {
return city;
}
public String getAddress() {
return address;
}
public double getLat() {
return lat;
}
public double getLng() {
return lng;
}
@Override
public String toString() {
return id+": "+name+"\n"+list.toString()+"\n";
}
}

View File

@@ -0,0 +1,98 @@
package de.sebse.fuplanner.services.Canteen.types;
import android.content.Context;
import android.support.annotation.NonNull;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Iterator;
import de.sebse.fuplanner.tools.SortedListCanteen;
public class Canteens implements Serializable, Iterable<Canteen> {
public static final int[] availableCanteens = {27, 28, 42};
private static final String FILE_NAME = "CanteensSaving";
private SortedListCanteen list = new SortedListCanteen();
private Canteen getCanteen(int id) {
return this.list.getById(id);
}
public void addCanteen(int id, String name, String city, String address, double lat, double lng) {
Canteen canteen = new Canteen(id, name, city, address, lat, lng);
addCanteen(canteen);
}
private void addCanteen(Canteen canteen) {
this.list.add(canteen);
}
private int size() {
return this.list.size();
}
public Canteen get(int index) {
return this.list.get(index);
}
public void update(Canteens canteens) {
SortedListCanteen oldList = this.list;
this.list = canteens.list;
for (Canteen oldCanteen: oldList) {
Canteen newCanteen = getCanteen(oldCanteen.getId());
if (newCanteen != null) newCanteen.update(oldCanteen);
}
}
@NonNull
@Override
public Iterator<Canteen> iterator() {
return new Iterator<Canteen>() {
int i = 0;
@Override
public boolean hasNext() {
return i < size();
}
@Override
public Canteen next() {
return get(i++);
}
@Override
public void remove() {
throw new UnsupportedOperationException("You are not alloed to remove an entry!");
}
};
}
public static Canteens load(Context context) throws IOException, ClassNotFoundException {
FileInputStream fis = context.openFileInput(FILE_NAME);
ObjectInputStream is = new ObjectInputStream(fis);
Canteens modules = (Canteens) is.readObject();
is.close();
fis.close();
return modules;
}
public void save(Context context) throws IOException {
FileOutputStream fos = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(this);
os.close();
fos.close();
}
public void delete(Context context) {
context.deleteFile(FILE_NAME);
}
@Override
public String toString() {
return this.list.toString();
}
}

View File

@@ -0,0 +1,66 @@
package de.sebse.fuplanner.services.Canteen.types;
import android.support.annotation.NonNull;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Iterator;
import de.sebse.fuplanner.tools.SortedListMeal;
public class Day implements Serializable, Iterable<Meal> {
private final int canteenId;
private final Calendar calendar;
private boolean isClosed;
private SortedListMeal list = new SortedListMeal();
Day(Canteen canteen, Calendar calendar, boolean isClosed) {
this.canteenId = canteen.getId();
this.calendar = calendar;
this.isClosed = isClosed;
}
public Meal getMeal(Integer id) {
return this.list.getById(id);
}
public void addMeal(int id, String name, String category, double priceStdnt, double priceEmply, double priceOther, String[] notes) {
Meal meal = new Meal(id, name, category, priceStdnt, priceEmply, priceOther, notes);
this.list.add(meal);
}
public int size() {
return this.list.size();
}
public Meal get(int index) {
return this.list.get(index);
}
public void update(Day day) {
this.list = day.list;
}
@NonNull
@Override
public Iterator<Meal> iterator() {
return this.list.iterator();
}
public Calendar getCalendar() {
return calendar;
}
public boolean isClosed() {
return isClosed;
}
public int getCanteenId() {
return canteenId;
}
@Override
public String toString() {
return Canteen.calendarToKey(getCalendar())+"\n"+this.list+"\n";
}
}

View File

@@ -0,0 +1,119 @@
package de.sebse.fuplanner.services.Canteen.types;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Meal implements Serializable {
public static final int LIGHT_NONE = 0;
public static final int LIGHT_GREEN = 1;
public static final int LIGHT_YELLOW = 2;
public static final int LIGHT_RED = 3;
public static final int VEGAN_NONE = 0;
public static final int VEGAN_VEGETERIAN = 1;
public static final int VEGAN_VEGAN = 2;
public static final int CERT_NONE = 0b0000;
public static final int CERT_BIO = 0b0001;
public static final int CERT_MSC = 0b0010;
private final int id;
private final String name;
private final String category;
private final double priceStdnt;
private final double priceEmply;
private final double priceOther;
private final List<String> notes;
private final int light;
private final int vegan;
private final int certificates;
Meal(int id, String name, String category, double priceStdnt, double priceEmply, double priceOther, String[] notes) {
this.id = id;
this.name = name;
this.category = category;
this.priceStdnt = priceStdnt;
this.priceEmply = priceEmply;
this.priceOther = priceOther;
int light = LIGHT_NONE;
int vegan = VEGAN_NONE;
int certificates = CERT_NONE;
List<String> filteredNotes = new ArrayList<>();
for (String note : notes) {
switch (note.toLowerCase()) {
case "vegetarisch":
vegan = VEGAN_VEGETERIAN;
break;
case "vegan":
vegan = VEGAN_VEGAN;
break;
case "bio":
certificates += CERT_BIO;
break;
case "msc":
certificates += CERT_MSC;
break;
case "grün (ampel)":
light = LIGHT_GREEN;
break;
case "gelb (ampel)":
light = LIGHT_YELLOW;
break;
case "rot (ampel)":
light = LIGHT_RED;
break;
default:
filteredNotes.add(note);
}
}
this.light = light;
this.vegan = vegan;
this.certificates = certificates;
this.notes = Collections.unmodifiableList(filteredNotes);
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getCategory() {
return category;
}
public double getPriceStdnt() {
return priceStdnt;
}
public double getPriceEmply() {
return priceEmply;
}
public double getPriceOther() {
return priceOther;
}
public List<String> getNotes() {
return notes;
}
public int getLight() {
return light;
}
public int getVegan() {
return vegan;
}
public int getCertificates() {
return certificates;
}
@Override
public String toString() {
return name + " (" + category + ")";
}
}

View File

@@ -77,7 +77,7 @@ public class KVV {
modules = new KVVModuleList(KVV.this.context, token); modules = new KVVModuleList(KVV.this.context, token);
addons.put("modules", modules); addons.put("modules", modules);
} }
modules.getModule(id, callback, error, forceRefresh); modules.getModule(id, saveOnCallback(modules, callback), error, forceRefresh);
}); });
} }
@@ -92,7 +92,7 @@ public class KVV {
modules = new KVVModuleList(KVV.this.context, token); modules = new KVVModuleList(KVV.this.context, token);
addons.put("modules", modules); addons.put("modules", modules);
} }
modules.getModuleList(callback, error, forceRefresh); modules.getModuleList(saveOnCallback(modules, callback), error, forceRefresh);
}); });
} }

View File

@@ -112,9 +112,11 @@ public class KVVModuleList extends HTTPService {
modules.addModule(semester, lvNumbers, title, lecturers, type, description, id); modules.addModule(semester, lvNumbers, title, lecturers, type, description, id);
} }
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101102, 403, "Cannot parse module list!")); errorCallback.onError(new NetworkError(101102, 403, "Cannot parse module list!"));
return; return;
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101103, 403, "Cannot parse module list!")); errorCallback.onError(new NetworkError(101103, 403, "Cannot parse module list!"));
return; return;
} }
@@ -222,6 +224,7 @@ public class KVVModuleList extends HTTPService {
announcements.add(new Announcement(id, title, text, createdBy, createdOn)); announcements.add(new Announcement(id, title, text, createdBy, createdOn));
} }
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!")); errorCallback.onError(new NetworkError(101202, 403, "Cannot parse announcements!"));
return; return;
} }
@@ -286,6 +289,7 @@ public class KVVModuleList extends HTTPService {
assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls, instructions)); assignments.add(0, new Assignment(id, title, dueTime, gradebookItemName, gradeScale, urls, instructions));
} }
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!")); errorCallback.onError(new NetworkError(101302, 403, "Cannot parse announcements!"));
return; return;
} }
@@ -341,6 +345,7 @@ public class KVVModuleList extends HTTPService {
events.add(new Event(id, type, title, duration, firstTime)); events.add(new Event(id, type, title, duration, firstTime));
} }
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101402, 403, "Cannot parse calendar entries!")); errorCallback.onError(new NetworkError(101402, 403, "Cannot parse calendar entries!"));
return; return;
} }
@@ -394,6 +399,7 @@ public class KVVModuleList extends HTTPService {
} }
}catch (JSONException e) { }catch (JSONException e) {
e.printStackTrace();
errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook for announcements!")); errorCallback.onError(new NetworkError(101502, 403, "Cannot parse gradebook for announcements!"));
return; return;
} }

View File

@@ -13,8 +13,8 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
public class Conversion { public class DateUtils {
private static Logger log = new Logger("Conversion"); private static Logger log = new Logger("DateUtils");
@Deprecated @Deprecated
public static String getModifiedDateTime(long modified) { public static String getModifiedDateTime(long modified) {

View File

@@ -0,0 +1,118 @@
package de.sebse.fuplanner.tools;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public abstract class SortedList<T, I, F> implements Iterable<T>, Serializable {
private ArrayList<T> internalList = new ArrayList<>();
public void add(T e) {
internalList.add(e);
Collections.sort(internalList, this::compare);
}
public void remove(int index) {
this.internalList.remove(index);
}
abstract int compare(T o1, T o2);
abstract boolean hasIdentifier(T o1, I id);
abstract boolean hasFilter(T o1, F filter);
@Nullable
public T get(int i) {
return internalList.get(i);
}
@Nullable
public T getById(I id) {
for (T item : this.internalList) {
if (hasIdentifier(item, id))
return item;
}
return null;
}
public int size() {
return internalList.size();
}
@NonNull
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int pos = -1;
@Override
public boolean hasNext() {
return pos+1 < internalList.size();
}
@Override
public T next() {
pos++;
if (pos < internalList.size())
return internalList.get(pos);
return null;
}
@Override
public void remove() {
throw new UnsupportedOperationException("no changes allowed");
}
};
}
public Iterator<T> filteredIterator(F filter) {
return new Iterator<T>() {
private int index = -1;
private int next = -1;
@Override
public boolean hasNext() {
if (index==next)
predict();
return next != -1;
}
@Override
public T next() {
if (index == next)
predict();
if (next == -1)
return null;
index = next;
return internalList.get(index);
}
@Override
public void remove() {
throw new UnsupportedOperationException("no changes allowed");
}
private void predict() {
int size = internalList.size();
do {
next++;
} while (next < size && decline(internalList.get(next)));
if (next == size)
next = -1;
}
private boolean decline(T ob){
return !hasFilter(ob, filter);
}
};
}
@Override
public String toString() {
return this.internalList.toString();
}
}

View File

@@ -0,0 +1,21 @@
package de.sebse.fuplanner.tools;
import de.sebse.fuplanner.services.Canteen.types.Canteen;
public class SortedListCanteen extends SortedList<Canteen, Integer, String> {
@Override
int compare(Canteen o1, Canteen o2) {
// TODO correct implementation
return Integer.compare(o1.getId(), o2.getId());
}
@Override
boolean hasIdentifier(Canteen o1, Integer id) {
return o1.getId() == id;
}
@Override
boolean hasFilter(Canteen o1, String filter) {
return o1.getCity().equals(filter);
}
}

View File

@@ -0,0 +1,24 @@
package de.sebse.fuplanner.tools;
import java.util.Calendar;
import de.sebse.fuplanner.services.Canteen.types.Canteen;
import de.sebse.fuplanner.services.Canteen.types.Day;
public class SortedListDay extends SortedList<Day, Calendar, String> {
@Override
int compare(Day o1, Day o2) {
// TODO correct implementation
return Canteen.calendarToKey(o1.getCalendar()).compareTo(Canteen.calendarToKey(o2.getCalendar()));
}
@Override
boolean hasIdentifier(Day o1, Calendar id) {
return Canteen.calendarToKey(o1.getCalendar()).equals(Canteen.calendarToKey(id));
}
@Override
boolean hasFilter(Day o1, String filter) {
return false;
}
}

View File

@@ -0,0 +1,20 @@
package de.sebse.fuplanner.tools;
import de.sebse.fuplanner.services.Canteen.types.Meal;
public class SortedListMeal extends SortedList<Meal, Integer, String> {
@Override
int compare(Meal o1, Meal o2) {
return Integer.compare(o1.getId(), o2.getId());
}
@Override
boolean hasIdentifier(Meal o1, Integer id) {
return o1.getId() == id;
}
@Override
boolean hasFilter(Meal o1, String filter) {
return o1.getCategory().equals(filter);
}
}

View File

@@ -13,7 +13,7 @@ import de.sebse.fuplanner.services.KVV.types.Modules;
public class SortedModuleList extends AbstractList<Modules.Module> implements Serializable { public class SortedModuleList extends AbstractList<Modules.Module> implements Serializable {
private ArrayList<Modules.Module> internalList = new ArrayList<Modules.Module>(); private ArrayList<Modules.Module> internalList = new ArrayList<>();
// Note that add(E e) in AbstractList is calling this one // Note that add(E e) in AbstractList is calling this one
@Override @Override
@@ -27,7 +27,6 @@ public class SortedModuleList extends AbstractList<Modules.Module> implements Se
}); });
} }
@Deprecated
@Override @Override
public Modules.Module get(int i) { public Modules.Module get(int i) {
return internalList.get(i); return internalList.get(i);

View File

@@ -47,7 +47,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import de.sebse.fuplanner.R; import de.sebse.fuplanner.R;
import de.sebse.fuplanner.tools.Conversion; import de.sebse.fuplanner.tools.DateUtils;
import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.daysBetween; import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.daysBetween;
import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.getPassedMinutesInDay; import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.getPassedMinutesInDay;
@@ -1619,7 +1619,7 @@ public class WeekView extends View {
@Override @Override
public String interpretDate(Calendar date) { public String interpretDate(Calendar date) {
try { try {
return Conversion.getModifiedDate(getContext(), date.getTimeInMillis(), "EEE dd.M").toUpperCase(); return DateUtils.getModifiedDate(getContext(), date.getTimeInMillis(), "EEE dd.M").toUpperCase();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return ""; return "";