Skip to content

Commit

Permalink
PDIO-259 Add real-time item start and end time support
Browse files Browse the repository at this point in the history
  • Loading branch information
dszeto committed Jan 21, 2014
1 parent 6906c20 commit 477300e
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import io.prediction.commons.settings.{ Algo, App, Engine, OfflineEval }

import scala.util.Random

import com.github.nscala_time.time.Imports._

trait ItemRecAlgoOutput {
/** output the Seq of iids */
def output(uid: String, n: Int, itypes: Option[Seq[String]])(implicit app: App, algo: Algo, offlineEval: Option[OfflineEval]): Iterator[String]
Expand All @@ -31,17 +33,29 @@ object ItemRecAlgoOutput {
* of documents that can be returned from a query with geospatial constraint is 100.
* A "manual join" is still feasible with this size.
*/
val iids: Iterator[String] = latlng.map { ll =>
val (iids, iidsCopy): (Iterator[String], Iterator[String]) = latlng.map { ll =>
val geoItems = items.getByAppidAndLatlng(app.id, ll, within, unit).map(_.id).toSet
// use n = 0 to return all available iids for now
ItemRecCFAlgoOutput.output(uid, 0, itypes).filter { geoItems(_) }
}.getOrElse {
// use n = 0 to return all available iids for now
ItemRecCFAlgoOutput.output(uid, 0, itypes)
}
}.duplicate

/** Start and end time filtering. */
val itemsForTimeCheck = items.getByIds(app.id, iidsCopy.toSeq)
val iidsWithValidTimeSet = (itemsForTimeCheck filter { item =>
(item.starttime, item.endtime) match {
case (Some(st), None) => DateTime.now >= st
case (None, Some(et)) => DateTime.now <= et
case (Some(st), Some(et)) => st <= DateTime.now && DateTime.now <= et
case _ => true
}
} map { _.id }).toSet
val iidsWithValidTime: Iterator[String] = iids.filter { iidsWithValidTimeSet(_) }

/** At this point "output" is guaranteed to have n*(s+1) items (seen or unseen) unless model data is exhausted. */
val output = iids.take(finalN).toList
val output = iidsWithValidTime.take(finalN).toList

/** Serendipity output. */
val serendipityOutput = serendipity.map { s =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class AlgoOutputSelectorSpec extends Specification {
p ^
"get itemrec output from a valid engine" ! itemRecOutputSelection(algoOutputSelector) ^
"get itemrec output with geo from a valid engine" ! itemRecOutputSelectionWithLatlng(algoOutputSelector) ^
"get itemrec output with time constraints from a valid engine" ! itemRecOutputSelectionWithTime(algoOutputSelector) ^
//"get itemrec output from a valid engine without seen items" ! itemRecOutputSelectionUnseenOnly(algoOutputSelector) ^
//"get itemrec output from a valid engine with an unsupported algorithm" ! itemRecOutputSelectionUnsupportedAlgo(algoOutputSelector) ^
"get itemrec output from a valid engine with no algorithm" ! itemRecOutputSelectionNoAlgo(algoOutputSelector) ^
Expand Down Expand Up @@ -264,7 +265,7 @@ class AlgoOutputSelectorSpec extends Specification {
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.now.hour(14).minute(13)),
starttime = Some(DateTime.now),
endtime = None,
price = Some(49.394),
profit = None,
Expand All @@ -276,7 +277,7 @@ class AlgoOutputSelectorSpec extends Specification {
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.now.hour(23).minute(13)),
starttime = Some(DateTime.now),
endtime = None,
price = Some(49.394),
profit = None,
Expand All @@ -288,7 +289,7 @@ class AlgoOutputSelectorSpec extends Specification {
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.now.hour(17).minute(13)),
starttime = Some(DateTime.now),
endtime = None,
price = Some(49.394),
profit = None,
Expand All @@ -300,7 +301,7 @@ class AlgoOutputSelectorSpec extends Specification {
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.now.hour(3).minute(13)),
starttime = Some(DateTime.now),
endtime = None,
price = Some(49.394),
profit = None,
Expand Down Expand Up @@ -330,6 +331,120 @@ class AlgoOutputSelectorSpec extends Specification {
algoOutputSelector.itemRecSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(2.2), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "dac"))
}

def itemRecOutputSelectionWithTime(algoOutputSelector: AlgoOutputSelector) = {
val appid = dummyApp.id
val engine = Engine(
id = 0,
appid = appid,
name = "itemRecOutputSelectionWithTime",
infoid = "itemrec",
itypes = Some(Seq("foo", "bar")),
params = Map()
)
val engineid = mongoEngines.insert(engine)

val algo = Algo(
id = 0,
engineid = engineid,
name = "itemRecOutputSelectionWithTime",
infoid = "pdio-knnitembased",
command = "itemRecOutputSelectionWithTime",
params = Map("foo" -> "bar"),
settings = Map("dead" -> "beef"),
modelset = true,
createtime = DateTime.now,
updatetime = DateTime.now,
status = "deployed",
offlineevalid = None
)
val algoid = mongoAlgos.insert(algo)

val id = "itemRecOutputSelectionWithTime"

val dac = Item(
id = id + "dac",
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.now),
endtime = None,
price = Some(49.394),
profit = None,
latlng = Some((37.3197611, -122.0466141)),
inactive = None,
attributes = Some(Map("foo" -> "bar", "foo2" -> "bar2")))
val hsh = Item(
id = id + "hsh",
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = Some(DateTime.lastHour),
endtime = None,
price = Some(49.394),
profit = None,
latlng = Some((37.3370801, -122.0493201)),
inactive = None,
attributes = None)
val mvh = Item(
id = id + "mvh",
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = None,
endtime = Some(DateTime.nextHour),
price = Some(49.394),
profit = None,
latlng = Some((37.3154153, -122.0566829)),
inactive = None,
attributes = Some(Map("foo3" -> "bar3")))
val lbh = Item(
id = id + "lbh",
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = None,
endtime = Some(DateTime.lastHour),
price = Some(49.394),
profit = None,
latlng = Some((37.2997029, -122.0034684)),
inactive = None,
attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
val lbh2 = Item(
id = id + "lbh2",
appid = appid,
ct = DateTime.now,
itypes = List("fresh", "meat"),
starttime = None,
endtime = None,
price = Some(49.394),
profit = None,
latlng = Some((37.2997029, -122.0034684)),
inactive = None,
attributes = Some(Map("foo4" -> "bar4", "foo5" -> "bar5")))
val allItems = Seq(dac, hsh, lbh, lbh2, mvh)
allItems foreach { mongoItems.insert(_) }

val scores: Seq[(String, Double, Seq[String])] = Seq(
// (iid, score, itypes)
(id + "hsh", 5, Seq("foo")),
(id + "mvh", 4, Seq("foo")),
(id + "lbh", 3, Seq("bar")),
(id + "lbh2", 2, Seq("bar")),
(id + "dac", 1, Seq("bar")))

mongoItemRecScores.insert(ItemRecScore(
uid = "user1",
iids = scores.map(_._1),
scores = scores.map(_._2),
itypes = scores.map(_._3),
appid = dummyApp.id,
algoid = algoid,
modelset = true
))

algoOutputSelector.itemRecSelection("user1", 10, None, Some((37.3229978, -122.0321823)), Some(10), None)(dummyApp, engine.copy(id = engineid)) must beEqualTo(Seq(id + "hsh", id + "mvh", id + "lbh2", id + "dac"))
}

def itemRecOutputSelectionUnseenOnly(algoOutputSelector: AlgoOutputSelector) = {
val engine = Engine(
id = 0,
Expand Down

0 comments on commit 477300e

Please sign in to comment.