OESFeedQueue is an advanced library for queue management which replace the Lru way of caching. It sorts the items as per their score, which is calculated based on Recency, Frequency, Access times & Custom Parameters.
To include OESFeedQueue dependency into your app,
implementation 'com.bamfaltech:oescoreengine-core:1.0.0'
To Use OESFeedQueue follow the below steps,
- Create a model class implementing the OESFeedItem, where you should define below method,
fun getUniqueId(): String
fun getValue(key: String): String?
fun setValue(key: String, value: String)
- Define the input keys and their weightage which will contribute into the score calculation.
var inputKeyList = ArrayList<InputKey>()
inputKeyList.add(InputKey(Constants.RECENCY_KEY, InputKey.CURRENT_TIMESTAMP, Constants.DEFAULT_RECENCY_WEIGHTAGE))
inputKeyList.add(InputKey(Constants.FREQUENCY_KEY, InputKey.FREQUENCY, Constants.DEFAULT_FREQUENCY_WEIGHTAGE))
inputKeyList.add(InputKey(Constants.ACCESS_DURATION, InputKey.CUSTOM, Constants.DEFAULT_ACCESS_WEIGHTAGE))
inputKeyList.add(InputKey("custom_key", InputKey.CUSTOM, 0.1f))
For most common keys, such as Recency, Frequency & access time, we have defined key names and their weightage.
Default weightage are defined based on our multiple experiments, so I encourage to use them but still each value is customizable
- Initialise the OESFeedQueue with the List of data which we already saved into persistant storage such as Database,
It should be the return as. list where T is the model class which we defined in step 1
oesFeedQueue.prePopulateQueue(getStoredItemList())
//getStoredItemList will return the data from DB as List<T extends OESFeedItem>, </br>
// Below is the sample code which keeps track of app launch by a specific user
/**
* This should ideally be populated from persistant storage such as database
*/
fun getStoredItemList(): ArrayList<ModelClass> {
var list = ArrayList<ModelClass>()
var baseTime = System.currentTimeMillis()
Log.v("order", baseTime.toString())
//Consider the case when user accessed Twitter, then Whatsapp,then Linkedin and then facebook
//and all are open 5 times and 5 sec is the duration for which they accessed it
//1
var valueMap1 = HashMap<String, String>()
valueMap1.put(Constants.RECENCY_KEY, baseTime.toString())//time should come from stored DB
valueMap1.put(Constants.FREQUENCY_KEY, "5")
valueMap1.put(Constants.ACCESS_DURATION, "5")
list.add(ModelClass("1", "Linkedin", Constants.SCORE_NOT_SET, map=valueMap1))
//2
var valueMap2 = HashMap<String, String>()
valueMap2.put(Constants.RECENCY_KEY, (baseTime + 500).toString())
valueMap2.put(Constants.FREQUENCY_KEY, "5")
valueMap2.put(Constants.ACCESS_DURATION, "5")
list.add(ModelClass("2", "Facebook", Constants.SCORE_NOT_SET, map=valueMap2))
//3
var valueMap3 = HashMap<String, String>()
valueMap3.put(Constants.RECENCY_KEY, (baseTime - 1000).toString())
valueMap3.put(Constants.FREQUENCY_KEY, "5")
valueMap3.put(Constants.ACCESS_DURATION, "5")
list.add(ModelClass("3", "Whatsapp", Constants.SCORE_NOT_SET, map=valueMap3))
//4
var valueMap4 = HashMap<String, String>()
valueMap4.put(Constants.RECENCY_KEY, (baseTime - 2000).toString())
valueMap4.put(Constants.FREQUENCY_KEY, "5")
valueMap4.put(Constants.ACCESS_DURATION, "5")
list.add(ModelClass("4", "Twitter", Constants.SCORE_NOT_SET, map=valueMap4))
return list
}
- setup is done, Now add the individual entry based on actions taken by user.
//User accessed facebook again
fun performFewOps() {
var valueMap1 = HashMap<String, String>()
valueMap1.put(Constants.RECENCY_KEY, System.currentTimeMillis().toString())//when adding entry then timestammp would be current time only
var freq = oesFeedQueue.getValueBySpecificKeyForItem("2", Constants.FREQUENCY_KEY)
if(TextUtils.isEmpty(freq)) {
valueMap1.put(Constants.FREQUENCY_KEY, "1")
} else {
val f = freq!!.toInt()
valueMap1.put(Constants.FREQUENCY_KEY, (f+1).toString())
}
valueMap1.put(Constants.ACCESS_DURATION, "20")
var modelClass = ModelClass("2", "Facebook", Constants.SCORE_NOT_SET, map=valueMap1)
oesFeedQueue.addItem(modelClass)
}
- Finally test the logic, if it is sorted as expected or not :)
fun showAndCheckTheData() {
var list = oesFeedQueue.getSortedList(Constants.Descending)
var resultString = StringBuilder()
for(item in list) {
Log.v("order", "name : " + item.name + " | score : " + item.score)
resultString.append("name : " + item.name + " | score : " + item.score + " \n")
}
findViewById<TextView>(R.id.result).setText(resultString.toString())
}
- Here is the result,
2021-10-28 23:59:02.729 11053-11053/com.oescoreengine V/order: name : Facebook | score : 280.0
2021-10-28 23:59:02.729 11053-11053/com.oescoreengine V/order: name : Linkedin | score : 210.0
2021-10-28 23:59:02.729 11053-11053/com.oescoreengine V/order: name : Whatsapp | score : 209.96
2021-10-28 23:59:02.729 11053-11053/com.oescoreengine V/order: name : Twitter | score : 209.92
Please refer the sample code, to see the all implementation step by step
All public methods which are accessible,
fun getValueBySpecificKeyForItem(uniqueueId: String, key: String): String?
fun addItem(item: T)
fun removeLeastScoreItem(): T
fun prePopulateQueue(itemList: ArrayList<T>)
fun getSortedList(@Constants.SortOrder sortOrder: Int): ArrayList<T>
fun isItemExists(uniqueId: String): Boolean
fun getLeastScoreItem(): T
fun getHighestScoreItem(): T
fun clearQueue()