Archived
Flattened structure of StwParser.kt somewhat; CanteenFragment.kt now shows an error snack if the user tries to switch canteens while another one is being fetched; made slight adjustments to the translations
This commit is contained in:
@@ -98,6 +98,7 @@ class StwParser(application: Application) {
|
|||||||
onFinish()
|
onFinish()
|
||||||
|
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
|
// e.printStackTrace()
|
||||||
/*
|
/*
|
||||||
* Call action to let the user know an error occurred. Do this on the main thread to
|
* Call action to let the user know an error occurred. Do this on the main thread to
|
||||||
* access UI.
|
* access UI.
|
||||||
@@ -122,9 +123,6 @@ class StwParser(application: Application) {
|
|||||||
val categories = mutableListOf<OfferCategory>()
|
val categories = mutableListOf<OfferCategory>()
|
||||||
val items = mutableListOf<OfferItem>()
|
val items = mutableListOf<OfferItem>()
|
||||||
|
|
||||||
// Used to store a parsed date string without creating a new variable on every loop
|
|
||||||
var date: String
|
|
||||||
|
|
||||||
// Reset the primary key value for the date objects
|
// Reset the primary key value for the date objects
|
||||||
dateId = 0
|
dateId = 0
|
||||||
|
|
||||||
@@ -150,30 +148,16 @@ class StwParser(application: Application) {
|
|||||||
// Iterate through each day for which offers are available
|
// Iterate through each day for which offers are available
|
||||||
doc.getElementsByClass("food-plan").forEach { dayPlan ->
|
doc.getElementsByClass("food-plan").forEach { dayPlan ->
|
||||||
|
|
||||||
/*
|
// Get and add the date of this food plan
|
||||||
* Fetch the date for a given day. It will be in the following format:
|
dates.add(doc.getDateByIndex(dateId))
|
||||||
* 24. Apr
|
|
||||||
* This value will be split between the day (24.) and the month (Apr)
|
|
||||||
*/
|
|
||||||
val rawDate = doc.getElementsByClass("tabs")[0]
|
|
||||||
.getElementsByClass("tab-date")[dateId].text().split(" ")
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parse the two elements into a single date. The month will be converted to a numeric
|
|
||||||
* value. Example:
|
|
||||||
* Input: 24. Apr
|
|
||||||
* Output: 24.04.
|
|
||||||
*/
|
|
||||||
date = "${rawDate[0]}${rawDate[1].monthToNumber()}."
|
|
||||||
|
|
||||||
// Save the date to its list
|
|
||||||
dates.add(OfferDate(dateId, date))
|
|
||||||
|
|
||||||
|
// Set that the newly created date has no items as of yet
|
||||||
dateHasItems = false
|
dateHasItems = false
|
||||||
|
|
||||||
// Iterate through all categories offered on a given day
|
// Iterate through all categories offered on a given day
|
||||||
dayPlan.getElementsByClass("food-category").forEach { category ->
|
dayPlan.getElementsByClass("food-category").forEach { category ->
|
||||||
|
|
||||||
|
// Set that items for the newly created date have been found
|
||||||
dateHasItems = true
|
dateHasItems = true
|
||||||
|
|
||||||
// Retrieve the category text
|
// Retrieve the category text
|
||||||
@@ -183,67 +167,46 @@ class StwParser(application: Application) {
|
|||||||
categories.add(OfferCategory(categoryId, dateId, canteenId, categoryTitle))
|
categories.add(OfferCategory(categoryId, dateId, canteenId, categoryTitle))
|
||||||
|
|
||||||
// Iterate through all items in a category
|
// Iterate through all items in a category
|
||||||
category
|
category.getAllFoodItems().forEach { element ->
|
||||||
.getElementsByTag("tbody")[0]
|
// Retrieve the parent element holding the item's title and price
|
||||||
.getElementsByTag("tr").forEach { element ->
|
val tableRows = element.getElementsByTag("td")
|
||||||
// Retrieve the parent element holding the item's title and price
|
|
||||||
val tableRows = element.getElementsByTag("td")
|
|
||||||
|
|
||||||
/*
|
// Retrieve the dietary preferences the item meets
|
||||||
* Retrieve the dietary preferences the item meets and parse them into a
|
val prefs = getOrElse(DietaryPreferences.NONE_MET) {
|
||||||
* string that can be inserted into the database.
|
element
|
||||||
*/
|
.getElementsByClass("field field-name-field-food-types")[0]
|
||||||
val prefs = try {
|
.getDietaryPreferencesObject()
|
||||||
with(element
|
|
||||||
.getElementsByClass("field field-name-field-food-types")[0]
|
|
||||||
) {
|
|
||||||
DietaryPreferences.Object(
|
|
||||||
isFair = isDietaryPreferenceMet(preferenceFairFileName),
|
|
||||||
isFish = isDietaryPreferenceMet(preferenceFishFileName),
|
|
||||||
isPoultry = isDietaryPreferenceMet(preferencePoultryFileName),
|
|
||||||
isLamb = isDietaryPreferenceMet(preferenceLambFileName),
|
|
||||||
isVital = isDietaryPreferenceMet(preferenceVitalFileName),
|
|
||||||
isBeef = isDietaryPreferenceMet(preferenceBeefFileName),
|
|
||||||
isPork = isDietaryPreferenceMet(preferencePorkFileName),
|
|
||||||
isVegan = isDietaryPreferenceMet(preferenceVeganFileName),
|
|
||||||
isVegetarian = isDietaryPreferenceMet(preferenceVegetarianFileName),
|
|
||||||
isGame = isDietaryPreferenceMet(preferenceGameFileName),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e: IndexOutOfBoundsException) {
|
|
||||||
DietaryPreferences.NONE_MET
|
|
||||||
}
|
|
||||||
|
|
||||||
val filteredText = getOrElse(orElse = Pair("", "")) {
|
|
||||||
tableRows[1].getFilteredText()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the item to its list
|
|
||||||
items.add(
|
|
||||||
OfferItem(
|
|
||||||
itemId,
|
|
||||||
categoryId,
|
|
||||||
title = filteredText.first,
|
|
||||||
price = tableRows.getTextOrEmpty(
|
|
||||||
/*
|
|
||||||
* ID stored for student: 0
|
|
||||||
* Index required to fetch student price: 2
|
|
||||||
*
|
|
||||||
* ID stored for employee: 1
|
|
||||||
* Index required to fetch employee price: 3
|
|
||||||
*
|
|
||||||
* Hence, getIntPreference() + 2
|
|
||||||
*/
|
|
||||||
repo.getIntPreference(SettingsPreferences.PRICING) + 2
|
|
||||||
),
|
|
||||||
dietaryPreferences = prefs.deconstruct(),
|
|
||||||
allergens = filteredText.second,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Increment the item ID to avoid conflict
|
|
||||||
itemId += 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve title and embedded allergens individually
|
||||||
|
val filteredText = getOrElse(orElse = Pair("", "")) {
|
||||||
|
tableRows[1].splitTitleAndAllergens()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the item to its list
|
||||||
|
items.add(OfferItem(
|
||||||
|
itemId,
|
||||||
|
categoryId,
|
||||||
|
title = filteredText.first,
|
||||||
|
price = tableRows.getTextOrEmpty(
|
||||||
|
/*
|
||||||
|
* ID stored for student: 0
|
||||||
|
* Index required to fetch student price: 2
|
||||||
|
*
|
||||||
|
* ID stored for employee: 1
|
||||||
|
* Index required to fetch employee price: 3
|
||||||
|
*
|
||||||
|
* Hence, getIntPreference() + 2
|
||||||
|
*/
|
||||||
|
repo.getIntPreference(SettingsPreferences.PRICING) + 2
|
||||||
|
),
|
||||||
|
dietaryPreferences = prefs.deconstruct(),
|
||||||
|
allergens = filteredText.second,
|
||||||
|
))
|
||||||
|
|
||||||
|
// Increment the item ID to avoid conflict
|
||||||
|
itemId += 1
|
||||||
|
}
|
||||||
// Increment the category ID to avoid conflict
|
// Increment the category ID to avoid conflict
|
||||||
categoryId += 1
|
categoryId += 1
|
||||||
}
|
}
|
||||||
@@ -278,6 +241,44 @@ class StwParser(application: Application) {
|
|||||||
return StwResults(dates, canteens, categories, items)
|
return StwResults(dates, canteens, categories, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a date object from the canteen website by its index.
|
||||||
|
*
|
||||||
|
* @receiver document to parse
|
||||||
|
* @param index position to retrieve date from
|
||||||
|
* @return date object
|
||||||
|
*/
|
||||||
|
private fun Document.getDateByIndex(index: Int): OfferDate {
|
||||||
|
/*
|
||||||
|
* Fetch the date for a given day. It will be in the following format:
|
||||||
|
* 24. Apr
|
||||||
|
* This value will be split between the day (24.) and the month (Apr)
|
||||||
|
*/
|
||||||
|
val rawDate = getElementsByClass("tabs")[0]
|
||||||
|
.getElementsByClass("tab-date")[index].text().split(" ")
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse the two elements into a single date. The month will be converted to a numeric
|
||||||
|
* value. Example:
|
||||||
|
* Input: 24. Apr
|
||||||
|
* Output: 24.04.
|
||||||
|
*/
|
||||||
|
val date = "${rawDate[0]}${rawDate[1].monthToNumber()}."
|
||||||
|
|
||||||
|
// Save the date to its list
|
||||||
|
return OfferDate(dateId, date)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all food items from a given element for a given day.
|
||||||
|
*
|
||||||
|
* @receiver element to retrieve food item elements from
|
||||||
|
* @return list of food elements
|
||||||
|
*/
|
||||||
|
private fun Element.getAllFoodItems(): Elements =
|
||||||
|
getElementsByTag("tbody")[0].getElementsByTag("tr")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates whether a dietary preference is met by checking if the link to an image can be
|
* Evaluates whether a dietary preference is met by checking if the link to an image can be
|
||||||
* found in the HTML.
|
* found in the HTML.
|
||||||
@@ -293,6 +294,27 @@ class StwParser(application: Application) {
|
|||||||
).isNotEmpty()
|
).isNotEmpty()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Retrieves a dietary preferences object from a given Element.
|
||||||
|
*
|
||||||
|
* @receiver element to retrieve preferences from
|
||||||
|
* @return [DietaryPreferences.Object]
|
||||||
|
*/
|
||||||
|
private fun Element.getDietaryPreferencesObject(): DietaryPreferences.Object =
|
||||||
|
DietaryPreferences.Object(
|
||||||
|
isFair = isDietaryPreferenceMet(preferenceFairFileName),
|
||||||
|
isFish = isDietaryPreferenceMet(preferenceFishFileName),
|
||||||
|
isPoultry = isDietaryPreferenceMet(preferencePoultryFileName),
|
||||||
|
isLamb = isDietaryPreferenceMet(preferenceLambFileName),
|
||||||
|
isVital = isDietaryPreferenceMet(preferenceVitalFileName),
|
||||||
|
isBeef = isDietaryPreferenceMet(preferenceBeefFileName),
|
||||||
|
isPork = isDietaryPreferenceMet(preferencePorkFileName),
|
||||||
|
isVegan = isDietaryPreferenceMet(preferenceVeganFileName),
|
||||||
|
isVegetarian = isDietaryPreferenceMet(preferenceVegetarianFileName),
|
||||||
|
isGame = isDietaryPreferenceMet(preferenceGameFileName),
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the item's title and its dietary preferences that are embedded in its title.
|
||||||
* Processes certain character references into human-readable characters. Since the fetched HTML
|
* Processes certain character references into human-readable characters. Since the fetched HTML
|
||||||
* contains unresolved symbols such as &, they need to be replaced with their counterpart
|
* contains unresolved symbols such as &, they need to be replaced with their counterpart
|
||||||
* (in this case, &). This method also parses allergens and additives, since they are listed on
|
* (in this case, &). This method also parses allergens and additives, since they are listed on
|
||||||
@@ -300,9 +322,9 @@ class StwParser(application: Application) {
|
|||||||
* website user.
|
* website user.
|
||||||
*
|
*
|
||||||
* @receiver element to parse the text content of
|
* @receiver element to parse the text content of
|
||||||
* @return the filtered string and a string describing allergens and additives
|
* @return the filtered title and a string describing allergens and additives
|
||||||
*/
|
*/
|
||||||
private fun Element.getFilteredText(): Pair<String, String> {
|
private fun Element.splitTitleAndAllergens(): Pair<String, String> {
|
||||||
// Retrieve the element's inner HTML and replace faulty characters
|
// Retrieve the element's inner HTML and replace faulty characters
|
||||||
var text = html()
|
var text = html()
|
||||||
.replace("&", "&")
|
.replace("&", "&")
|
||||||
|
|||||||
@@ -153,8 +153,22 @@ class CanteenFragment : AppFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up floating action button for switching the canteen
|
// Set up floating action button for switching canteens
|
||||||
binding.fabSwitchCanteen.setOnClickListener {
|
binding.fabSwitchCanteen.setOnClickListener {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Show an error message is the user is trying to switch canteens while another one is
|
||||||
|
* being downloaded.
|
||||||
|
*/
|
||||||
|
if (binding.swipeRefreshLayout.isRefreshing) {
|
||||||
|
context.theme.showErrorSnackBar(
|
||||||
|
binding.snackbarContainer,
|
||||||
|
getString(R.string.canteen_fab_switch_canteen_error),
|
||||||
|
)
|
||||||
|
return@setOnClickListener
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create menu for selecting a new canteen
|
||||||
PopupMenu(binding.root.context, binding.fabSwitchCanteen).apply {
|
PopupMenu(binding.root.context, binding.fabSwitchCanteen).apply {
|
||||||
setOnMenuItemClickListener { item ->
|
setOnMenuItemClickListener { item ->
|
||||||
viewModel.preferenceCanteen = when (item?.itemId) {
|
viewModel.preferenceCanteen = when (item?.itemId) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
<string name="sheet_schedule_update_header_edit">Bestehende Veranstaltung bearbeiten</string>
|
<string name="sheet_schedule_update_header_edit">Bestehende Veranstaltung bearbeiten</string>
|
||||||
<string name="sheet_schedule_update_header_add">Neue Veranstaltung hinzufügen</string>
|
<string name="sheet_schedule_update_header_add">Neue Veranstaltung hinzufügen</string>
|
||||||
<string name="sheet_schedule_update_title_hint">Veranstaltungstitel</string>
|
<string name="sheet_schedule_update_title_hint">Veranstaltungstitel</string>
|
||||||
<string name="sheet_schedule_update_lecturers_hint">Dozierende(r)</string>
|
<string name="sheet_schedule_update_lecturers_hint">Dozierende*r</string>
|
||||||
<string name="sheet_schedule_update_room_hint">Raum</string>
|
<string name="sheet_schedule_update_room_hint">Raum</string>
|
||||||
<string name="sheet_schedule_update_hint_quarter">Auf akademisches Viertel umstellen</string>
|
<string name="sheet_schedule_update_hint_quarter">Auf akademisches Viertel umstellen</string>
|
||||||
<string name="sheet_schedule_update_hint_quarter_error">Sorry, ein Fehler ist aufgetreten!</string>
|
<string name="sheet_schedule_update_hint_quarter_error">Sorry, ein Fehler ist aufgetreten!</string>
|
||||||
@@ -68,7 +68,8 @@
|
|||||||
<string name="canteen_no_offer_desc">Für diesen Tag sind keine Angebote vorhanden</string>
|
<string name="canteen_no_offer_desc">Für diesen Tag sind keine Angebote vorhanden</string>
|
||||||
<string name="canteen_news_sheet_title">Neuigkeiten für diese Mensa</string>
|
<string name="canteen_news_sheet_title">Neuigkeiten für diese Mensa</string>
|
||||||
<string name="canteen_fab_opening_hours_content_desc">Zeige Öffnungszeiten</string>
|
<string name="canteen_fab_opening_hours_content_desc">Zeige Öffnungszeiten</string>
|
||||||
<string name="canteen_fab_switch_canteen">Wechsle Mensa</string>
|
<string name="canteen_fab_switch_canteen">Mensa wechseln</string>
|
||||||
|
<string name="canteen_fab_switch_canteen_error">Ein Plan wird gerade heruntergeladen.</string>
|
||||||
<string name="canteen_fab_refresh_content_desc">Aktualisiere Angebote</string>
|
<string name="canteen_fab_refresh_content_desc">Aktualisiere Angebote</string>
|
||||||
<string name="canteen_fab_refresh_text">Aktualisieren</string>
|
<string name="canteen_fab_refresh_text">Aktualisieren</string>
|
||||||
|
|
||||||
@@ -145,7 +146,7 @@
|
|||||||
<string name="allergen_almonds">Mandeln</string>
|
<string name="allergen_almonds">Mandeln</string>
|
||||||
<string name="allergen_hazelnuts">Haselnüsse</string>
|
<string name="allergen_hazelnuts">Haselnüsse</string>
|
||||||
<string name="allergen_walnuts">Walnüsse</string>
|
<string name="allergen_walnuts">Walnüsse</string>
|
||||||
<string name="allergen_cashew_nuts">Cashew-Kerne</string>
|
<string name="allergen_cashew_nuts">Cashewkerne</string>
|
||||||
<string name="allergen_pecans">Pecannüsse</string>
|
<string name="allergen_pecans">Pecannüsse</string>
|
||||||
<string name="allergen_brazil_nuts">Paranüsse</string>
|
<string name="allergen_brazil_nuts">Paranüsse</string>
|
||||||
<string name="allergen_pistachios">Pistazien</string>
|
<string name="allergen_pistachios">Pistazien</string>
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
<string name="canteen_news_sheet_title">News for this canteen</string>
|
<string name="canteen_news_sheet_title">News for this canteen</string>
|
||||||
<string name="canteen_fab_opening_hours_content_desc">Show opening hours</string>
|
<string name="canteen_fab_opening_hours_content_desc">Show opening hours</string>
|
||||||
<string name="canteen_fab_switch_canteen">Switch canteen</string>
|
<string name="canteen_fab_switch_canteen">Switch canteen</string>
|
||||||
|
<string name="canteen_fab_switch_canteen_error">A plan is being downloaded.</string>
|
||||||
<string name="canteen_fab_refresh_content_desc">Refresh offers</string>
|
<string name="canteen_fab_refresh_content_desc">Refresh offers</string>
|
||||||
<string name="canteen_fab_refresh_text">Refresh</string>
|
<string name="canteen_fab_refresh_text">Refresh</string>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user