ref: 69fe211f7d555e696a6901b743bd6676b7dc79ee
app/src/main/java/ml/adamsprogs/bimba/CacheManager.kt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
package ml.adamsprogs.bimba import android.content.Context import android.content.SharedPreferences import ml.adamsprogs.bimba.models.Plate class CacheManager private constructor(context: Context) { companion object { private var manager: CacheManager? = null fun getCacheManager(context: Context): CacheManager { return if (manager == null) { manager = CacheManager(context) manager!! } else manager!! } val MAX_SIZE = 40 } private var cachePreferences: SharedPreferences = context.getSharedPreferences("ml.adamsprogs.bimba.cachePreferences.cache", Context.MODE_PRIVATE) private var cacheHitsPreferences: SharedPreferences = context.getSharedPreferences("ml.adamsprogs.bimba.cachePreferences.cacheHits", Context.MODE_PRIVATE) private var cache: HashMap<String, Plate> = HashMap() private var cacheHits: HashMap<String, Int> = HashMap() fun keys(): List<Plate> { return cache.map { Plate(it.key.split("@")[0], it.key.split("@")[1], null) } } fun hasAll(plates: HashSet<Plate>): Boolean { plates .filterNot { has(it) } .forEach { return false } return true } fun hasAny(plates: HashSet<Plate>): Boolean { plates .filter { has(it) } .forEach { return true } return false } fun has(plate: Plate): Boolean { return cache.containsKey(key(plate)) } fun push(plates: HashSet<Plate>) { val removeNumber = cache.size + plates.size - MAX_SIZE val editor = cachePreferences.edit() val editorCacheHits = cacheHitsPreferences.edit() cacheHits.map { "${it.value}|${it.key}" }.sortedBy { it }.slice(0 until removeNumber).forEach { val key = it.split("|")[1] cache.remove(key) editor.remove(key) } for (plate in plates) { val key = key(plate) cache[key] = plate cacheHits[key] = 0 editor.putString(key, cache[key].toString()) editorCacheHits.putInt(key, 0) } editor.apply() editorCacheHits.apply() } fun push(plate: Plate) { val editorCache = cachePreferences.edit() val editorCacheHits = cacheHitsPreferences.edit() if (cacheHits.size == MAX_SIZE) { val key = cacheHits.minBy { it.value }?.key cache.remove(key) editorCache.remove(key) cacheHits.remove(key) editorCacheHits.remove(key) } val key = key(plate) cache[key] = plate cacheHits[key] = 0 editorCache.putString(key, plate.toString()) editorCacheHits.putInt(key, 0) editorCache.apply() editorCacheHits.apply() } fun get(plates: HashSet<Plate>): HashSet<Plate> { val result = HashSet<Plate>() for (plate in plates) { val value = get(plate) if (value == null) result.add(plate) else result.add(value) } return result } fun get(plate: Plate): Plate? { if (!has(plate)) return null val key = key(plate) val hits = cacheHits[key] if (hits != null) cacheHits[key] = hits + 1 return cache[key] } fun recreate(stopDeparturesByPlates: Set<Plate>) { stopDeparturesByPlates.forEach { cache[key(it)] = it } } init { cache = cacheFromString(cachePreferences.all) @Suppress("UNCHECKED_CAST") cacheHits = cacheHitsPreferences.all as HashMap<String, Int> } private fun cacheFromString(preferences: Map<String, *>): HashMap<String, Plate> { val result = HashMap<String, Plate>() for ((key, value) in preferences.entries) { result[key] = Plate.fromString(value as String) } return result } private fun key(plate: Plate) = "${plate.line}@${plate.stop}" } |