From a72accada6d6b5836bf77b8a6b63cf5676643b49 Mon Sep 17 00:00:00 2001
From: denizk0461
Date: Fri, 12 Jan 2024 17:19:58 +0100
Subject: [PATCH] Days (Monday thru Friday) are now shown on the canteen screen
---
.../23.json | 393 ++++++++++++++++++
.../denizk0461/weserplaner/data/StwParser.kt | 8 +-
.../denizk0461/weserplaner/db/AppDatabase.kt | 11 +-
.../weserplaner/fragment/CanteenFragment.kt | 6 +-
.../denizk0461/weserplaner/model/OfferDate.kt | 2 +
.../weserplaner/values/SettingsPreferences.kt | 5 +
6 files changed, 419 insertions(+), 6 deletions(-)
create mode 100644 app/schemas/com.denizk0461.weserplaner.db.AppDatabase/23.json
diff --git a/app/schemas/com.denizk0461.weserplaner.db.AppDatabase/23.json b/app/schemas/com.denizk0461.weserplaner.db.AppDatabase/23.json
new file mode 100644
index 0000000..7340f09
--- /dev/null
+++ b/app/schemas/com.denizk0461.weserplaner.db.AppDatabase/23.json
@@ -0,0 +1,393 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 23,
+ "identityHash": "8e471de9f5f6c5f301676106d46ed5a1",
+ "entities": [
+ {
+ "tableName": "timetables",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "name",
+ "columnName": "name",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "studip_events",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`eventId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timetableId` INTEGER NOT NULL, `title` TEXT NOT NULL, `lecturer` TEXT NOT NULL, `room` TEXT NOT NULL, `day` INTEGER NOT NULL, `timeslotStart` TEXT NOT NULL, `timeslotEnd` TEXT NOT NULL, `timeslotId` INTEGER NOT NULL, `colour` INTEGER NOT NULL, FOREIGN KEY(`timetableId`) REFERENCES `timetables`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "eventId",
+ "columnName": "eventId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timetableId",
+ "columnName": "timetableId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lecturer",
+ "columnName": "lecturer",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "day",
+ "columnName": "day",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeslotStart",
+ "columnName": "timeslotStart",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeslotEnd",
+ "columnName": "timeslotEnd",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timeslotId",
+ "columnName": "timeslotId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "colour",
+ "columnName": "colour",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "eventId"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "timetables",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "timetableId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "offer_date",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `day` TEXT NOT NULL, `date` TEXT NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "day",
+ "columnName": "day",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "date",
+ "columnName": "date",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "offer_canteen",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `canteen` TEXT NOT NULL, `openingHours` TEXT NOT NULL, `news` TEXT NOT NULL, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canteen",
+ "columnName": "canteen",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "openingHours",
+ "columnName": "openingHours",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "news",
+ "columnName": "news",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "offer_category",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `dateId` INTEGER NOT NULL, `canteenId` INTEGER NOT NULL, `category` TEXT NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`dateId`) REFERENCES `offer_date`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`canteenId`) REFERENCES `offer_canteen`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "dateId",
+ "columnName": "dateId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "canteenId",
+ "columnName": "canteenId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "category",
+ "columnName": "category",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "offer_date",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "dateId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ },
+ {
+ "table": "offer_canteen",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "canteenId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "offer_item",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`itemId` INTEGER NOT NULL, `categoryId` INTEGER NOT NULL, `title` TEXT NOT NULL, `price` TEXT NOT NULL, `dietary_preferences` TEXT NOT NULL, `allergens` TEXT NOT NULL, PRIMARY KEY(`itemId`), FOREIGN KEY(`categoryId`) REFERENCES `offer_category`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "itemId",
+ "columnName": "itemId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "categoryId",
+ "columnName": "categoryId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "price",
+ "columnName": "price",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "dietaryPreferences",
+ "columnName": "dietary_preferences",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "allergens",
+ "columnName": "allergens",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "itemId"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "offer_category",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "categoryId"
+ ],
+ "referencedColumns": [
+ "id"
+ ]
+ }
+ ]
+ },
+ {
+ "tableName": "event_tasks",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`taskId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `eventId` INTEGER NOT NULL, `dueDate` INTEGER NOT NULL, `notifyDate` INTEGER NOT NULL, `title` TEXT NOT NULL, `notes` TEXT NOT NULL, `room` TEXT NOT NULL, `isFinished` INTEGER NOT NULL, FOREIGN KEY(`eventId`) REFERENCES `studip_events`(`eventId`) ON UPDATE NO ACTION ON DELETE CASCADE )",
+ "fields": [
+ {
+ "fieldPath": "taskId",
+ "columnName": "taskId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "eventId",
+ "columnName": "eventId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "dueDate",
+ "columnName": "dueDate",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "notifyDate",
+ "columnName": "notifyDate",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "notes",
+ "columnName": "notes",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "room",
+ "columnName": "room",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "isFinished",
+ "columnName": "isFinished",
+ "affinity": "INTEGER",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "taskId"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": [
+ {
+ "table": "studip_events",
+ "onDelete": "CASCADE",
+ "onUpdate": "NO ACTION",
+ "columns": [
+ "eventId"
+ ],
+ "referencedColumns": [
+ "eventId"
+ ]
+ }
+ ]
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8e471de9f5f6c5f301676106d46ed5a1')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/denizk0461/weserplaner/data/StwParser.kt b/app/src/main/java/com/denizk0461/weserplaner/data/StwParser.kt
index b7a3147..975db12 100644
--- a/app/src/main/java/com/denizk0461/weserplaner/data/StwParser.kt
+++ b/app/src/main/java/com/denizk0461/weserplaner/data/StwParser.kt
@@ -254,6 +254,9 @@ class StwParser(application: Application) {
* @return date object
*/
private fun Document.getDateByIndex(index: Int): OfferDate {
+ val day = getElementsByClass("tabs")[0]
+ .getElementsByClass("tab-title")[index].text()
+
/*
* Fetch the date for a given day. It will be in the following format:
* 24. Apr
@@ -272,7 +275,7 @@ class StwParser(application: Application) {
val date = "${rawDate[0]}${rawDate[1].monthToNumber()}."
// Save the date to its list
- return OfferDate(dateId, date)
+ return OfferDate(dateId, day, date)
}
/**
@@ -438,7 +441,8 @@ class StwParser(application: Application) {
* Cleans up a HTML source by doing the following:
* - replace non-breaking spaces ' ' with a regular space character ' ',
* - replace closing paragraph tags '
' with a line break '\n', and
- * - remove any other tag.
+ * - remove any other tag that does not start with 'a' or 'b' – this is a hacky way to preserve
+ * and
tags.
* This is used to format the opening hours of the canteens.
*
* @receiver Element to parse the text of
diff --git a/app/src/main/java/com/denizk0461/weserplaner/db/AppDatabase.kt b/app/src/main/java/com/denizk0461/weserplaner/db/AppDatabase.kt
index d445aa9..614d70b 100644
--- a/app/src/main/java/com/denizk0461/weserplaner/db/AppDatabase.kt
+++ b/app/src/main/java/com/denizk0461/weserplaner/db/AppDatabase.kt
@@ -22,7 +22,7 @@ import com.denizk0461.weserplaner.model.*
OfferItem::class,
EventTask::class,
],
- version = 22,
+ version = 23,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 20, to = 21),
@@ -61,6 +61,7 @@ abstract class AppDatabase : RoomDatabase() {
).addMigrations(
migrationAddNewsToOfferCanteen_19_20,
migration_21_22,
+ migration_22_23,
// migrationAddTimetableId_20_21,
// migrationAddEventTask_20_21,
)
@@ -125,5 +126,13 @@ abstract class AppDatabase : RoomDatabase() {
database.execSQL("ALTER TABLE studip_events_temp RENAME TO studip_events")
}
}
+
+ private val migration_22_23 = object : Migration(22, 23) {
+ override fun migrate(database: SupportSQLiteDatabase) {
+ database.execSQL("""
+ ALTER TABLE offer_date ADD COLUMN day TEXT NOT NULL DEFAULT '?'
+ """)
+ }
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt
index 0588ea9..faafcc8 100644
--- a/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt
+++ b/app/src/main/java/com/denizk0461/weserplaner/fragment/CanteenFragment.kt
@@ -40,7 +40,7 @@ class CanteenFragment : AppFragment() {
/**
* Locally stored dates to populate the TabLayout with.
*/
- private var dates: List = listOf()
+ private var dates: List = listOf()
// Instantiate the view binding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@@ -219,7 +219,7 @@ class CanteenFragment : AppFragment() {
viewModel.getDates().observe(viewLifecycleOwner) { newDates ->
// Retrieve the dates individually and store them for the tab mediator to use
- dates = newDates.map { it.date }
+ dates = newDates
// Let the adapter know of the new amount of dates (pages) to display
viewPagerAdapter.itemCount = dates.size
@@ -230,7 +230,7 @@ class CanteenFragment : AppFragment() {
// Set up TabLayoutMediator to populate tabs
TabLayoutMediator(binding.dayTabLayout, binding.viewPager) { tab, position ->
- tab.text = dates[position]
+ tab.text = dates[position].run { "$day, $date" }
}.attach()
// Set extended FAB to extend when the page is changed
diff --git a/app/src/main/java/com/denizk0461/weserplaner/model/OfferDate.kt b/app/src/main/java/com/denizk0461/weserplaner/model/OfferDate.kt
index 0c54d1b..baabc00 100644
--- a/app/src/main/java/com/denizk0461/weserplaner/model/OfferDate.kt
+++ b/app/src/main/java/com/denizk0461/weserplaner/model/OfferDate.kt
@@ -7,6 +7,7 @@ import androidx.room.PrimaryKey
* Entity for binding several canteen items to a specific date. Registered in the app database.
*
* @param id primary key that uniquely identifies the item
+ * @param day the day. that's it. pretty self-explanatory, eh?
* @param date date formatted as dd.MM.
*/
@Entity(
@@ -14,5 +15,6 @@ import androidx.room.PrimaryKey
)
data class OfferDate(
@PrimaryKey val id: Int,
+ val day: String,
val date: String,
)
diff --git a/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt b/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt
index ce46777..de961f6 100644
--- a/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt
+++ b/app/src/main/java/com/denizk0461/weserplaner/values/SettingsPreferences.kt
@@ -88,5 +88,10 @@ enum class SettingsPreferences(val key: String) {
* Which timetable the user has selected.
*/
SELECTED_TIMETABLE("selected_timetable"),
+
+ /**
+ * How the dates should be shown on the canteen screen.
+ */
+ CANTEEN_DATE_PREFERENCE("date_canteen_preference")
;
}
\ No newline at end of file