{"action":"created","comment":{"url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/comments/79304544","id":79304544,"diff_hunk":"@@ -19,130 +19,194 @@ package org.template\n \n import grizzled.slf4j.Logger\n import io.prediction.data.storage.Event\n+import io.prediction.data.store.PEventStore\n import org.apache.spark.SparkContext\n import org.apache.spark.rdd.RDD\n-import io.prediction.data.store.PEventStore\n import org.joda.time.format.ISODateTimeFormat\n-import org.joda.time.{DateTime, Interval}\n+import org.joda.time.{ DateTime, Interval }\n+import org.template.conversions.{ ItemID, ItemProps }\n+\n+import scala.language.postfixOps\n+import scala.util.Random\n+\n+object RankingFieldName {\n+  val UserRank = \"userRank\"\n+  val UniqueRank = \"uniqueRank\"\n+  val PopRank = \"popRank\"\n+  val TrendRank = \"trendRank\"\n+  val HotRank = \"hotRank\"\n+  val UnknownRank = \"unknownRank\"\n+  def toSeq: Seq[String] = Seq(UserRank, UniqueRank, PopRank, TrendRank, HotRank)\n+  override def toString: String = s\"$UserRank, $UniqueRank, $PopRank, $TrendRank, $HotRank\"\n+}\n \n+object RankingType {\n+  val Popular = \"popular\"\n+  val Trending = \"trending\"\n+  val Hot = \"hot\"\n+  val UserDefined = \"userDefined\"\n+  val Random = \"random\"\n+  def toSeq: Seq[String] = Seq(Popular, Trending, Hot, UserDefined, Random)\n+  override def toString: String = s\"$Popular, $Trending, $Hot, $UserDefined, $Random\"\n+}\n \n-object PopModel {\n+class PopModel(fieldsRDD: RDD[(ItemID, ItemProps)])(implicit sc: SparkContext) {\n \n-  @transient lazy val logger = Logger[this.type]\n+  @transient lazy val logger: Logger = Logger[this.type]\n \n-  def calc (\n-    modelName: Option[String] = None,\n-    eventNames: List[String],\n+  def calc(\n+    modelName: String,\n+    eventNames: Seq[String],\n     appName: String,\n     duration: Int = 0,\n-    offsetDate: Option[String] = None)(implicit sc: SparkContext): Option[RDD[(String, Float)]] = {\n+    offsetDate: Option[String] = None): RDD[(ItemID, Double)] = {\n \n     // todo: make end manditory and fill it with \"now\" upstream if not specified, will simplify logic here\n     // end should always be 'now' except in unusual conditions like for testing\n-    val end = if (offsetDate.isEmpty ) DateTime.now else {\n+    val end = if (offsetDate.isEmpty) DateTime.now else {\n       try {\n         ISODateTimeFormat.dateTimeParser().parseDateTime(offsetDate.get)\n       } catch {\n-        case e: IllegalArgumentException => e\n+        case e: IllegalArgumentException =>\n           logger.warn(\"Bad end for popModel: \" + offsetDate.get + \" using 'now'\")\n           DateTime.now\n       }\n     }\n \n+    val interval = new Interval(end.minusSeconds(duration), end)\n+\n     // based on type of popularity model return a set of (item-id, ranking-number) for all items\n-    logger.info(s\"PopModel ${modelName} using end: ${end}, and duration: ${duration} \")\n+    logger.info(s\"PopModel $modelName using end: $end, and duration: $duration, interval: $interval\")\n+\n+    // if None? debatable, this is either an error or may need to default to popular, why call popModel otherwise\n     modelName match {\n-      case Some(\"popular\") => calcPopular(appName, eventNames, new Interval(end.minusSeconds(duration), end))\n-      case Some(\"trending\") => calcTrending(appName, eventNames, new Interval(end.minusSeconds(duration), end))\n-      case Some(\"hot\") => calcHot(appName, eventNames, new Interval(end.minusSeconds(duration), end))\n-      case _ => None // debatable, this is either an error or may need to default to popular, why call popModel otherwise\n+      case RankingType.Popular     => calcPopular(appName, eventNames, interval)\n+      case RankingType.Trending    => calcTrending(appName, eventNames, interval)\n+      case RankingType.Hot         => calcHot(appName, eventNames, interval)\n+      case RankingType.Random      => calcRandom(appName, interval)\n+      case RankingType.UserDefined => sc.emptyRDD\n+      case unknownRankingType =>\n+        logger.warn(\n+          s\"\"\"\n+             |Bad rankings param type=[$unknownRankingType] in engine definition params, possibly a bad json value.\n+             |Use one of the available parameter values ($RankingType).\"\"\".stripMargin)\n+        sc.emptyRDD\n     }\n+\n   }\n \n-  /** Creates a rank from the number of named events per item for the duration */\n-  def calcPopular(appName: String, eventNames: List[String] = List.empty,\n-    interval: Interval)(implicit sc: SparkContext): Option[RDD[(String, Float)]] = {\n+  /** Create random rank for all items */\n+  def calcRandom(\n+    appName: String,\n+    interval: Interval): RDD[(ItemID, Double)] = {\n+\n+    val events = eventsRDD(appName = appName, interval = interval)\n+    val actionsRDD = events.map(_.targetEntityId).filter(_.isDefined).map(_.get).distinct()\n+    val itemsRDD = fieldsRDD.map { case (itemID, _) => itemID }\n+\n+    //    logger.debug(s\"ActionsRDD: ${actionsRDD.take(25).mkString(\", \")}\")\n+    //    logger.debug(s\"ItemsRDD: ${itemsRDD.take(25).mkString(\", \")}\")\n+    actionsRDD.union(itemsRDD).distinct().map { itemID => itemID -> Random.nextDouble() }\n+  }\n \n+  /** Creates a rank from the number of named events per item for the duration */\n+  def calcPopular(\n+    appName: String,\n+    eventNames: Seq[String],\n+    interval: Interval): RDD[(ItemID, Double)] = {\n     val events = eventsRDD(appName, eventNames, interval)\n-    val retval = events.map { e => (e.targetEntityId, e.event) }\n+    events.map { e => (e.targetEntityId, e.event) }\n       .groupByKey()\n-      .map { case(itemID, itEvents) => (itemID.get, itEvents.size.toFloat)}\n-      .reduceByKey (_+_) // make this a double in Elaseticsearch)\n-    if (!retval.isEmpty()) Some(retval) else None\n+      .map { case (itemID, itEvents) => (itemID.get, itEvents.size.toDouble) }\n+      .reduceByKey(_ + _) // make this a double in Elaseticsearch)\n   }\n \n   /** Creates a rank for each item by dividing the duration in two and counting named events in both buckets\n-    * then dividing most recent by less recent. This ranks by change in popularity or velocity of populatiy change.\n-    * Interval(start, end) end instant is always greater than or equal to the start instant.\n-    */\n-  def calcTrending(appName: String, eventNames: List[String] = List.empty,\n-    interval: Interval)(implicit sc: SparkContext): Option[RDD[(String, Float)]] = {\n+   *  then dividing most recent by less recent. This ranks by change in popularity or velocity of populatiy change.\n+   *  Interval(start, end) end instant is always greater than or equal to the start instant.\n+   */\n+  def calcTrending(\n+    appName: String,\n+    eventNames: Seq[String],\n+    interval: Interval): RDD[(ItemID, Double)] = {\n \n-    val olderInterval = new Interval(interval.getStart,\n-      interval.getStart().plusMillis((interval.toDurationMillis/2)toInt))\n-    val newerInterval = new Interval(interval.getStart().plusMillis((interval.toDurationMillis/2)toInt), interval.getEnd)\n+    logger.info(s\"Current Interval: $interval, ${interval.toDurationMillis}\")\n+    val halfInterval = interval.toDurationMillis / 2\n+    val olderInterval = new Interval(interval.getStart, interval.getStart.plus(halfInterval))\n+    logger.info(s\"Older Interval: $olderInterval\")\n+    val newerInterval = new Interval(interval.getStart.plus(halfInterval), interval.getEnd)\n+    logger.info(s\"Newer Interval: $newerInterval\")\n \n-    val intervalMillis = interval.toDurationMillis\n     val olderPopRDD = calcPopular(appName, eventNames, olderInterval)\n-    if ( olderPopRDD.nonEmpty) {\n+    if (!olderPopRDD.isEmpty()) {\n       val newerPopRDD = calcPopular(appName, eventNames, newerInterval)\n-      if ( newerPopRDD.nonEmpty ) {\n-        val retval = newerPopRDD.get.join(olderPopRDD.get).map { case (item, (newerScore, olderScore)) =>\n-          val velocity = (newerScore - olderScore)\n-          (item, velocity)\n-        }\n-        if (!retval.isEmpty()) Some(retval) else None\n-      } else None\n-    } else None\n+      newerPopRDD.join(olderPopRDD).map {\n+        case (item, (newerScore, olderScore)) => item -> (newerScore - olderScore)\n+      }\n+    } else sc.emptyRDD\n+\n   }\n \n   /** Creates a rank for each item by divding all events per item into three buckets and calculating the change in\n-    * velocity over time, in other words the acceleration of popularity change.\n-    */\n-  def calcHot(appName: String, eventNames: List[String] = List.empty,\n-    interval: Interval)(implicit sc: SparkContext): Option[RDD[(String, Float)]] = {\n-    val olderInterval = new Interval(interval.getStart,\n-      interval.getStart().plusMillis((interval.toDurationMillis/3)toInt))\n-    val middleInterval = new Interval(olderInterval.getEnd,\n-      olderInterval.getEnd().plusMillis((olderInterval.toDurationMillis)toInt))\n+   *  velocity over time, in other words the acceleration of popularity change.\n+   */\n+  def calcHot(\n+    appName: String,\n+    eventNames: Seq[String] = List.empty,\n+    interval: Interval): RDD[(ItemID, Double)] = {\n+\n+    logger.info(s\"Current Interval: $interval, ${interval.toDurationMillis}\")\n+    val olderInterval = new Interval(interval.getStart, interval.getStart.plus(interval.toDurationMillis / 3))\n+    logger.info(s\"Older Interval: $olderInterval\")\n+    val middleInterval = new Interval(olderInterval.getEnd, olderInterval.getEnd.plus(olderInterval.toDurationMillis))\n+    logger.info(s\"Middle Interval: $middleInterval\")\n     val newerInterval = new Interval(middleInterval.getEnd, interval.getEnd)\n+    logger.info(s\"Newer Interval: $newerInterval\")\n \n     val olderPopRDD = calcPopular(appName, eventNames, olderInterval)\n-    if (olderPopRDD.nonEmpty){ // todo: may want to allow an interval with no events, give them 0 counts\n-      //val debug = olderPopRDD.get.count()\n+    if (!olderPopRDD.isEmpty()) { // todo: may want to allow an interval with no events, give them 0 counts\n       val middlePopRDD = calcPopular(appName, eventNames, middleInterval)\n-      if (middlePopRDD.nonEmpty){\n-        //val debug = middlePopRDD.get.count()\n+      if (!middlePopRDD.isEmpty()) {\n         val newerPopRDD = calcPopular(appName, eventNames, newerInterval)\n-        if (newerPopRDD.nonEmpty){\n-          //val debug = newerPopRDD.get.count()\n-          val newVelocityRDD = newerPopRDD.get.join(middlePopRDD.get).map { case( item, (newerScore, olderScore)) =>\n-            val velocity = (newerScore - olderScore)\n-            (item, velocity)\n-          }\n-          val oldVelocityRDD = middlePopRDD.get.join(olderPopRDD.get).map { case( item, (newerScore, olderScore)) =>\n-            val velocity = (newerScore - olderScore)\n-            (item, velocity)\n-          }\n-          Some( newVelocityRDD.join(oldVelocityRDD).map { case (item, (newVelocity, oldVelocity)) =>\n-            val acceleration = (newVelocity - oldVelocity)\n-            (item, acceleration)\n-          })\n-        } else None\n-      } else None\n-    } else None\n+        val newVelocityRDD = newerPopRDD.join(middlePopRDD).map {\n+          case (item, (newerScore, middleScore)) => item -> (newerScore - middleScore)\n+        }\n+        val oldVelocityRDD = middlePopRDD.join(olderPopRDD).map {\n+          case (item, (middleScore, olderScore)) => item -> (middleScore - olderScore)\n+        }\n+        newVelocityRDD.join(oldVelocityRDD).map {\n+          case (item, (newVelocity, oldVelocity)) => item -> (newVelocity - oldVelocity)\n+        }\n+      } else sc.emptyRDD\n+    } else sc.emptyRDD\n   }\n \n-  def eventsRDD(appName: String, eventNames: List[String], interval: Interval)\n-    (implicit sc: SparkContext): RDD[Event] = {\n+  def eventsRDD(\n+    appName: String,\n+    eventNames: Seq[String] = Seq.empty,\n+    interval: Interval): RDD[Event] = {\n \n-    //logger.info(s\"PopModel getting eventsRDD for startTime: ${interval.getStart} and endTime ${interval.getEnd}\")\n+    logger.info(s\"PopModel getting eventsRDD for startTime: ${interval.getStart} and endTime ${interval.getEnd}\")\n     PEventStore.find(\n       appName = appName,\n       startTime = Some(interval.getStart),\n       untilTime = Some(interval.getEnd),\n-      eventNames = Some(eventNames)\n-    )(sc)\n+      eventNames = if (eventNames.nonEmpty) Some(eventNames) else None)(sc)","path":"src/main/scala/PopModel.scala","position":250,"original_position":250,"commit_id":"3ce7c5b686125998bbb4e93f52085d6c6b89eb49","original_commit_id":"333c4c24f829490610913a9a6583141a4fb68aea","user":{"login":"laser13","id":1689628,"avatar_url":"https://avatars.githubusercontent.com/u/1689628?v=3","gravatar_id":"","url":"https://api.github.com/users/laser13","html_url":"https://github.com/laser13","followers_url":"https://api.github.com/users/laser13/followers","following_url":"https://api.github.com/users/laser13/following{/other_user}","gists_url":"https://api.github.com/users/laser13/gists{/gist_id}","starred_url":"https://api.github.com/users/laser13/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/laser13/subscriptions","organizations_url":"https://api.github.com/users/laser13/orgs","repos_url":"https://api.github.com/users/laser13/repos","events_url":"https://api.github.com/users/laser13/events{/privacy}","received_events_url":"https://api.github.com/users/laser13/received_events","type":"User","site_admin":false},"body":"If `eventNames` is empty, `eventsRDD` find all items with any action","created_at":"2016-09-18T12:26:34Z","updated_at":"2016-09-18T12:26:34Z","html_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23#discussion_r79304544","pull_request_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23","_links":{"self":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/comments/79304544"},"html":{"href":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23#discussion_r79304544"},"pull_request":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23"}}},"pull_request":{"url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23","id":83895890,"html_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23","diff_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23.diff","patch_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23.patch","issue_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/23","number":23,"state":"open","locked":false,"title":"Random rank","user":{"login":"laser13","id":1689628,"avatar_url":"https://avatars.githubusercontent.com/u/1689628?v=3","gravatar_id":"","url":"https://api.github.com/users/laser13","html_url":"https://github.com/laser13","followers_url":"https://api.github.com/users/laser13/followers","following_url":"https://api.github.com/users/laser13/following{/other_user}","gists_url":"https://api.github.com/users/laser13/gists{/gist_id}","starred_url":"https://api.github.com/users/laser13/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/laser13/subscriptions","organizations_url":"https://api.github.com/users/laser13/orgs","repos_url":"https://api.github.com/users/laser13/repos","events_url":"https://api.github.com/users/laser13/events{/privacy}","received_events_url":"https://api.github.com/users/laser13/received_events","type":"User","site_admin":false},"body":"In this PR I made a lot of changes, but mainly they are: fix of scala style error, turn imperative code to functional style. Business logic calculating \"cooccurrence\" and \"popular rank\" not changed.\r\n\r\n1. Added scalastyle sbt plugin, and code is checked.\r\n> sbt scalastyle\r\n\r\n2. Added scalariform sbt plugin, code is configured and formatted.\r\n> sbt scalariformFormat\r\n\r\n3. \"backfillField\" renamed to \"backfills\", and now is the array.\r\n\r\n4. backfill types now may be one of the value [\"popular\" OR \"hot\" OR \"trending\"] AND/OR \"userDefined\" AND/OR \"random\"\r\n\r\n5. backfill names are used as names in ES, but name with type \"userDefined\" must match with \"$set\" field name.\r\n\r\n6. Add to Query field \"withRanks\", if true, show rank fields in ItemScore as map(rankName -> rankValue)\r\n\r\n7. Base integration test is passed success\r\n\r\n8. Add new integration test \"integration-test-rank\". It uses other fixtures data and engine.json","created_at":"2016-09-03T13:38:17Z","updated_at":"2016-09-18T12:26:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8914b005b319f449b9a7b3381ebc2b70693cae8c","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23/commits","review_comments_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23/comments","review_comment_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/comments{/number}","comments_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/23/comments","statuses_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/statuses/3ce7c5b686125998bbb4e93f52085d6c6b89eb49","head":{"label":"laser13:randomRank","ref":"randomRank","sha":"3ce7c5b686125998bbb4e93f52085d6c6b89eb49","user":{"login":"laser13","id":1689628,"avatar_url":"https://avatars.githubusercontent.com/u/1689628?v=3","gravatar_id":"","url":"https://api.github.com/users/laser13","html_url":"https://github.com/laser13","followers_url":"https://api.github.com/users/laser13/followers","following_url":"https://api.github.com/users/laser13/following{/other_user}","gists_url":"https://api.github.com/users/laser13/gists{/gist_id}","starred_url":"https://api.github.com/users/laser13/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/laser13/subscriptions","organizations_url":"https://api.github.com/users/laser13/orgs","repos_url":"https://api.github.com/users/laser13/repos","events_url":"https://api.github.com/users/laser13/events{/privacy}","received_events_url":"https://api.github.com/users/laser13/received_events","type":"User","site_admin":false},"repo":{"id":66135184,"name":"template-scala-parallel-universal-recommendation","full_name":"laser13/template-scala-parallel-universal-recommendation","owner":{"login":"laser13","id":1689628,"avatar_url":"https://avatars.githubusercontent.com/u/1689628?v=3","gravatar_id":"","url":"https://api.github.com/users/laser13","html_url":"https://github.com/laser13","followers_url":"https://api.github.com/users/laser13/followers","following_url":"https://api.github.com/users/laser13/following{/other_user}","gists_url":"https://api.github.com/users/laser13/gists{/gist_id}","starred_url":"https://api.github.com/users/laser13/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/laser13/subscriptions","organizations_url":"https://api.github.com/users/laser13/orgs","repos_url":"https://api.github.com/users/laser13/repos","events_url":"https://api.github.com/users/laser13/events{/privacy}","received_events_url":"https://api.github.com/users/laser13/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/laser13/template-scala-parallel-universal-recommendation","description":null,"fork":true,"url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation","forks_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/forks","keys_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/teams","hooks_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/hooks","issue_events_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/issues/events{/number}","events_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/events","assignees_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/assignees{/user}","branches_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/branches{/branch}","tags_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/tags","blobs_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/git/refs{/sha}","trees_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/statuses/{sha}","languages_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/languages","stargazers_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/stargazers","contributors_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/contributors","subscribers_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/subscribers","subscription_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/subscription","commits_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/commits{/sha}","git_commits_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/git/commits{/sha}","comments_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/comments{/number}","issue_comment_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/issues/comments{/number}","contents_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/contents/{+path}","compare_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/merges","archive_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/downloads","issues_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/issues{/number}","pulls_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/pulls{/number}","milestones_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/milestones{/number}","notifications_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/labels{/name}","releases_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/releases{/id}","deployments_url":"https://api.github.com/repos/laser13/template-scala-parallel-universal-recommendation/deployments","created_at":"2016-08-20T07:46:53Z","updated_at":"2016-08-20T07:46:54Z","pushed_at":"2016-09-18T12:13:42Z","git_url":"git://github.com/laser13/template-scala-parallel-universal-recommendation.git","ssh_url":"git@github.com:laser13/template-scala-parallel-universal-recommendation.git","clone_url":"https://github.com/laser13/template-scala-parallel-universal-recommendation.git","svn_url":"https://github.com/laser13/template-scala-parallel-universal-recommendation","homepage":null,"size":3252,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"actionml:master","ref":"master","sha":"662675406d330e1444f1b0d65d3f714ed7997834","user":{"login":"actionml","id":14876181,"avatar_url":"https://avatars.githubusercontent.com/u/14876181?v=3","gravatar_id":"","url":"https://api.github.com/users/actionml","html_url":"https://github.com/actionml","followers_url":"https://api.github.com/users/actionml/followers","following_url":"https://api.github.com/users/actionml/following{/other_user}","gists_url":"https://api.github.com/users/actionml/gists{/gist_id}","starred_url":"https://api.github.com/users/actionml/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/actionml/subscriptions","organizations_url":"https://api.github.com/users/actionml/orgs","repos_url":"https://api.github.com/users/actionml/repos","events_url":"https://api.github.com/users/actionml/events{/privacy}","received_events_url":"https://api.github.com/users/actionml/received_events","type":"Organization","site_admin":false},"repo":{"id":48816733,"name":"template-scala-parallel-universal-recommendation","full_name":"actionml/template-scala-parallel-universal-recommendation","owner":{"login":"actionml","id":14876181,"avatar_url":"https://avatars.githubusercontent.com/u/14876181?v=3","gravatar_id":"","url":"https://api.github.com/users/actionml","html_url":"https://github.com/actionml","followers_url":"https://api.github.com/users/actionml/followers","following_url":"https://api.github.com/users/actionml/following{/other_user}","gists_url":"https://api.github.com/users/actionml/gists{/gist_id}","starred_url":"https://api.github.com/users/actionml/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/actionml/subscriptions","organizations_url":"https://api.github.com/users/actionml/orgs","repos_url":"https://api.github.com/users/actionml/repos","events_url":"https://api.github.com/users/actionml/events{/privacy}","received_events_url":"https://api.github.com/users/actionml/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation","description":"","fork":true,"url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation","forks_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/forks","keys_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/keys{/key_id}","collaborators_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/teams","hooks_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/hooks","issue_events_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/events{/number}","events_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/events","assignees_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/assignees{/user}","branches_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/branches{/branch}","tags_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/tags","blobs_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/git/refs{/sha}","trees_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/git/trees{/sha}","statuses_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/statuses/{sha}","languages_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/languages","stargazers_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/stargazers","contributors_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/contributors","subscribers_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/subscribers","subscription_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/subscription","commits_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/commits{/sha}","git_commits_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/git/commits{/sha}","comments_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/comments{/number}","issue_comment_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/comments{/number}","contents_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/contents/{+path}","compare_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/compare/{base}...{head}","merges_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/merges","archive_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/downloads","issues_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues{/number}","pulls_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls{/number}","milestones_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/milestones{/number}","notifications_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/labels{/name}","releases_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/releases{/id}","deployments_url":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/deployments","created_at":"2015-12-30T19:42:34Z","updated_at":"2016-09-13T21:50:02Z","pushed_at":"2016-09-18T12:13:42Z","git_url":"git://github.com/actionml/template-scala-parallel-universal-recommendation.git","ssh_url":"git@github.com:actionml/template-scala-parallel-universal-recommendation.git","clone_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation.git","svn_url":"https://github.com/actionml/template-scala-parallel-universal-recommendation","homepage":null,"size":3266,"stargazers_count":14,"watchers_count":14,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":15,"mirror_url":null,"open_issues_count":9,"forks":15,"open_issues":9,"watchers":14,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23"},"html":{"href":"https://github.com/actionml/template-scala-parallel-universal-recommendation/pull/23"},"issue":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/23"},"comments":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/issues/23/comments"},"review_comments":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23/comments"},"review_comment":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/pulls/23/commits"},"statuses":{"href":"https://api.github.com/repos/actionml/template-scala-parallel-universal-recommendation/statuses/3ce7c5b686125998bbb4e93f52085d6c6b89eb49"}}}}
{"actor":{"display_login":"laser13"}}