Successfully completed database change OMG; this will save memory by storing less duplicate data

This commit is contained in:
denizk0461
2023-04-17 14:19:06 +02:00
parent 4d520f375b
commit 315f2f815a
8 changed files with 137 additions and 57 deletions
@@ -1,7 +1,7 @@
package com.denizk0461.studip.data
import android.util.Log
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.db.EventRepository
import com.denizk0461.studip.model.*
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
@@ -9,10 +9,16 @@ import org.jsoup.select.Elements
// Parser class for the Studierendenwerk cafeteria plans
class StwParser {
private var id = 0
private var dateId = 0
private var canteenId = 0
private var categoryId = 0
private var itemId = 0
fun parse(onFinish: () -> Unit) {
id = 0
dateId = 0
canteenId = 0
categoryId = 0
itemId = 0
val links = mutableListOf<String>()
if (true) { links.add(urlUniMensa) }
// if (true) { links.add(urlCafeCentral) }
@@ -27,27 +33,39 @@ class StwParser {
Dependencies.repo.nukeOffers()
// STEP: fetch every canteen
links.forEach { link ->
Dependencies.repo.insertOffers(parseFromPage(link))
parseFromPage(link, Dependencies.repo)
}
}
private fun parseFromPage(url: String): List<CanteenOffer> {
private fun parseFromPage(url: String, repo: EventRepository): List<CanteenOffer> {
val items = mutableListOf<CanteenOffer>()
var date: String
var day = 0
dateId = 0
val doc = Jsoup.connect(url).get()
repo.insert(OfferCanteen(canteenId, "TEMP")) // TODO canteen name
// STEP: get each day
doc.getElementsByClass("food-plan").forEach { dayPlan ->
val rawDate = doc.getElementsByClass("tabs")[0]
.getElementsByClass("tab-date")[day].text().split(" ")
.getElementsByClass("tab-date")[dateId].text().split(" ")
date = "${rawDate[0]}${rawDate[1].monthToNumber()}."
day += 1
repo.insert(OfferDate(dateId, date))
// STEP: get each category in a day
dayPlan.getElementsByClass("food-category").forEach { category ->
val categoryTitle = category.getElementsByClass("category-name")[0].text()
repo.insert(OfferCategory(categoryId, dateId, canteenId, categoryTitle))
// STEP: get each item in a category
category
.getElementsByTag("tbody")[0]
.getElementsByTag("tr").forEach { element ->
@@ -56,11 +74,10 @@ class StwParser {
val prefs =
element.getElementsByClass("field field-name-field-food-types")[0]
val newItem = CanteenOffer(
id = id,
date = date,
dateId = day,
category = categoryTitle,
repo.insert(
OfferItem(
itemId,
categoryId,
title = tableRows[1].getFilteredText(),
price = tableRows.getTextOrEmpty(2),
isFair = prefs.isDietaryPreferenceMet(PREFERENCE_FAIR),
@@ -74,11 +91,33 @@ class StwParser {
isVegetarian = prefs.isDietaryPreferenceMet(PREFERENCE_VEGETARIAN),
isGame = prefs.isDietaryPreferenceMet(PREFERENCE_GAME),
)
items.add(newItem)
id += 1
)
itemId += 1
// val newItem = CanteenOffer(
// id = id,
// date = date,
// dateId = day,
// category = categoryTitle,
// title = tableRows[1].getFilteredText(),
//// price = tableRows.getTextOrEmpty(2),
// isFair = prefs.isDietaryPreferenceMet(PREFERENCE_FAIR),
// isFish = prefs.isDietaryPreferenceMet(PREFERENCE_FISH),
// isPoultry = prefs.isDietaryPreferenceMet(PREFERENCE_POULTRY),
// isLamb = prefs.isDietaryPreferenceMet(PREFERENCE_LAMB),
// isVital = prefs.isDietaryPreferenceMet(PREFERENCE_VITAL),
// isBeef = prefs.isDietaryPreferenceMet(PREFERENCE_BEEF),
// isPork = prefs.isDietaryPreferenceMet(PREFERENCE_PORK),
// isVegan = prefs.isDietaryPreferenceMet(PREFERENCE_VEGAN),
// isVegetarian = prefs.isDietaryPreferenceMet(PREFERENCE_VEGETARIAN),
// isGame = prefs.isDietaryPreferenceMet(PREFERENCE_GAME),
// )
}
categoryId += 1
}
dateId += 1
}
canteenId += 1
return items
}
@@ -4,12 +4,12 @@ import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.model.*
@Dao
interface EventDAO {
// Stud.IP schedule events
@get:Query("SELECT * FROM events ORDER BY id")
val allEvents: LiveData<List<StudIPEvent>>
@@ -22,12 +22,39 @@ interface EventDAO {
@Query("DELETE FROM events")
fun nukeEvents()
@get:Query("SELECT * FROM offers ORDER BY id")
// @get:Query("SELECT * FROM offers ORDER BY id")
// val allOffers: LiveData<List<CanteenOffer>>
//
// @Insert
// fun insertOffers(offers: List<CanteenOffer>)
//
// @Query("DELETE from offers")
// fun nukeOffers()
// canteen offers
// get all offers
@get:Query(
"SELECT * FROM offer_item " +
"JOIN offer_category ON offer_item.categoryId = offer_category.id " +
"JOIN offer_canteen ON offer_category.canteenId = offer_canteen.id " +
"JOIN offer_date ON offer_category.dateId = offer_date.id"
)
val allOffers: LiveData<List<CanteenOffer>>
@Insert
fun insertOffers(offers: List<CanteenOffer>)
@Query("DELETE FROM offer_date")
fun nukeOfferDates()
@Query("DELETE from offers")
fun nukeOffers()
@Query("DELETE FROM offer_category")
fun nukeOfferCategories()
@Query("DELETE FROM offer_canteen")
fun nukeOfferCanteens()
@Query("DELETE FROM offer_item")
fun nukeOfferItems()
@Insert fun insert(date: OfferDate)
@Insert fun insert(canteen: OfferCanteen)
@Insert fun insert(category: OfferCategory)
@Insert fun insert(item: OfferItem)
}
@@ -4,10 +4,18 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.model.*
@Database(entities = [StudIPEvent::class, CanteenOffer::class], version = 7)
@Database(
entities = [
StudIPEvent::class,
OfferDate::class,
OfferCanteen::class,
OfferCategory::class,
OfferItem::class
],
version = 8
)
abstract class EventDatabase : RoomDatabase() {
abstract fun dao(): EventDAO
@@ -2,8 +2,7 @@ package com.denizk0461.studip.db
import android.app.Application
import androidx.lifecycle.LiveData
import com.denizk0461.studip.model.CanteenOffer
import com.denizk0461.studip.model.StudIPEvent
import com.denizk0461.studip.model.*
class EventRepository(app: Application) {
@@ -17,6 +16,16 @@ class EventRepository(app: Application) {
val allOffers: LiveData<List<CanteenOffer>> = dao.allOffers
fun insertOffers(offers: List<CanteenOffer>) { dao.insertOffers(offers) }
fun nukeOffers() { dao.nukeOffers() }
// fun insertOffers(offers: List<CanteenOffer>) { dao.insertOffers(offers) }
fun nukeOffers() {
dao.nukeOfferItems()
dao.nukeOfferCategories()
dao.nukeOfferCanteens()
dao.nukeOfferDates()
}
fun insert(date: OfferDate) { dao.insert(date) }
fun insert(canteen: OfferCanteen) { dao.insert(canteen) }
fun insert(category: OfferCategory) { dao.insert(category) }
fun insert(item: OfferItem) { dao.insert(item) }
}
@@ -1,16 +1,15 @@
package com.denizk0461.studip.model
import androidx.room.Entity
import androidx.room.PrimaryKey
//@Entity(tableName = "offers")
data class CanteenOffer(
// @PrimaryKey val id: Int,
val id: Int,
val date: String,
val dateId: Int, // gives every item on the same day the same ID for easier filtering
// val canteen: Int,
val dateId: Int,
val category: String,
val categoryId: Int,
val canteen: String,
val canteenId: Int,
val title: String,
val price: String, // price for students
val isFair: Boolean, // artgerechte Tierhaltung
@@ -1,6 +1,5 @@
package com.denizk0461.studip.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@@ -11,20 +10,20 @@ import androidx.room.PrimaryKey
ForeignKey(
OfferDate::class,
["id"],
["date_id"],
["dateId"],
ForeignKey.CASCADE,
),
ForeignKey(
OfferCanteen::class,
["id"],
["canteen_id"],
["canteenId"],
ForeignKey.CASCADE,
),
]
)
data class OfferCategory(
@PrimaryKey val id: Int,
@ColumnInfo(name = "date_id") val dateId: Int,
@ColumnInfo(name = "canteen_id") val canteenId: Int,
val dateId: Int,
val canteenId: Int,
val category: String,
)
@@ -1,6 +1,5 @@
package com.denizk0461.studip.model
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@@ -11,15 +10,15 @@ import androidx.room.PrimaryKey
ForeignKey(
OfferCategory::class,
["id"],
["category_id"],
["categoryId"],
ForeignKey.CASCADE,
),
]
)
data class OfferItem(
@PrimaryKey val id: Int,
@ColumnInfo(name = "category_id") val categoryId: Int,
val title: Int,
val categoryId: Int,
val title: String,
val price: String,
val isFair: Boolean,
val isFish: Boolean,
@@ -11,7 +11,7 @@ class CanteenViewModel(app: Application) : TemplateViewModel(app) {
val allOffers: LiveData<List<CanteenOffer>> = repo.allOffers
fun insertOffers(offers: List<CanteenOffer>) { doAsync { repo.insertOffers(offers) }}
// fun insertOffers(offers: List<CanteenOffer>) { doAsync { repo.insertOffers(offers) }}
fun nukeOffers() { doAsync { repo.nukeOffers() }}
fun fetchOffers(onFinish: () -> Unit) { doAsync { parser.parse(onFinish) }}