{"action":"created","comment":{"url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/comments/170900564","pull_request_review_id":99655342,"id":170900564,"diff_hunk":"@@ -128,25 +202,248 @@ object Money {\n     def JPY = Money.JPY(amount)\n   }\n \n-  def EUR(amount: BigDecimal): Money = make(amount, Currency.getInstance(\"EUR\"))\n-  def USD(amount: BigDecimal): Money = make(amount, Currency.getInstance(\"USD\"))\n-  def GBP(amount: BigDecimal): Money = make(amount, Currency.getInstance(\"GBP\"))\n-  def JPY(amount: BigDecimal): Money = make(amount, Currency.getInstance(\"JPY\"))\n+  private def decimalAmountWithCurrencyAndHalfEvenRounding(amount: BigDecimal, currency: String) =\n+    fromDecimalAmount(amount, Currency.getInstance(currency))(BigDecimal.RoundingMode.HALF_EVEN)\n+\n+  def EUR(amount: BigDecimal): Money = decimalAmountWithCurrencyAndHalfEvenRounding(amount, \"EUR\")\n+  def USD(amount: BigDecimal): Money = decimalAmountWithCurrencyAndHalfEvenRounding(amount, \"USD\")\n+  def GBP(amount: BigDecimal): Money = decimalAmountWithCurrencyAndHalfEvenRounding(amount, \"GBP\")\n+  def JPY(amount: BigDecimal): Money = decimalAmountWithCurrencyAndHalfEvenRounding(amount, \"JPY\")\n+\n+  val TypeName = \"centAmount\"\n \n-  /** Creates a new Money object, forcing the scale according to the currency. */\n-  def make(amount: BigDecimal, currency: Currency, mode: RoundingMode): Money =\n+  def fromDecimalAmount(amount: BigDecimal, currency: Currency)(implicit mode: RoundingMode) =\n     Money(amount.setScale(currency.getDefaultFractionDigits, mode), currency)\n \n-  def make(amount: BigDecimal, currency: Currency): Money =\n-    make(amount, currency, BigDecimal.RoundingMode.HALF_EVEN)\n+  def fromCentAmount(centAmount: Long, currency: Currency) = {\n+    val centFactor = BigDecimal(1) / BigDecimal(10).pow(currency.getDefaultFractionDigits)\n+    val amount = BigDecimal(centAmount) * centFactor\n \n-  implicit def moneyMonoid(implicit c: Currency): Monoid[Money] = new Monoid[Money] {\n-    def combine(x: Money, y: Money): Money = x + y\n-    val empty: Money = Money.make(0, c)\n+    fromDecimalAmount(amount, currency)(BigDecimal.RoundingMode.UNNECESSARY)\n   }\n \n+  def zero(currency: Currency) =\n+    fromCentAmount(0L, currency)\n+\n   implicit def moneyMonoid(implicit c: Currency, mode: RoundingMode): Monoid[Money] = new Monoid[Money] {\n     def combine(x: Money, y: Money): Money = x + y\n-    val empty: Money = Money.make(0, c, mode)\n+    val empty: Money = Money.zero(c)\n+  }\n+}\n+\n+case class HighPrecisionMoney(amount: BigDecimal, fractionDigits: Int, centAmount: Long, currency: Currency) extends BaseMoney with Ordered[Money] {\n+  import HighPrecisionMoney._\n+\n+  require(amount.scale == fractionDigits,\n+    \"The scale of the given amount does not match the scale of the provided currency.\" +\n+    \" - \" + amount.scale + \" <-> \" + fractionDigits)\n+\n+  require(fractionDigits >= currency.getDefaultFractionDigits,\n+    \"`fractionDigits` should be  >= than the default fraction digits of the currency.\")\n+\n+  val `type` = TypeName\n+\n+  lazy val preciseAmountAsLong: Long =\n+    (amount * BigDecimal(10).pow(fractionDigits)).toLongExact\n+\n+  def withFractionDigits(fd: Int)(implicit mode: RoundingMode) = {\n+    val newAmount = amount.setScale(fd, mode)\n+\n+    HighPrecisionMoney(newAmount, fd, roundToCents(newAmount, currency), currency)\n+  }\n+\n+  def + (other: HighPrecisionMoney)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    calc(this, other, _ + _)\n+\n+  def + (m: Money)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this + m.toHighPrecisionMoney(fractionDigits)\n+\n+  def + (money: BaseMoney)(implicit mode: RoundingMode): BaseMoney = money match {\n+    case m: Money ⇒ this + m\n+    case m: HighPrecisionMoney ⇒ this + m\n+  }\n+\n+  def + (other: BigDecimal)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this + fromDecimalAmount(other, this.fractionDigits, this.currency)\n+\n+  def - (other: HighPrecisionMoney)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    calc(this, other, _ - _)\n+\n+  def - (m: Money)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this - m.toHighPrecisionMoney(fractionDigits)\n+\n+  def - (money: BaseMoney)(implicit mode: RoundingMode): BaseMoney = money match {\n+    case m: Money ⇒ this - m\n+    case m: HighPrecisionMoney ⇒ this - m\n+  }\n+\n+  def - (other: BigDecimal)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this - fromDecimalAmount(other, this.fractionDigits, this.currency)\n+\n+  def * (other: HighPrecisionMoney)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    calc(this, other, _ * _)\n+\n+  def * (m: Money)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this * m.toHighPrecisionMoney(fractionDigits)\n+\n+  def * (money: BaseMoney)(implicit mode: RoundingMode): BaseMoney = money match {\n+    case m: Money ⇒ this * m\n+    case m: HighPrecisionMoney ⇒ this * m\n+  }\n+  \n+  def * (other: BigDecimal)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this * fromDecimalAmount(other, this.fractionDigits, this.currency)\n+\n+  /** Divide to integral value + remainder */\n+  def /% (m: BigDecimal)(implicit mode: RoundingMode): (HighPrecisionMoney, HighPrecisionMoney) = {\n+    val (result, remainder) = this.amount /% m\n+\n+    fromDecimalAmount(result, fractionDigits, this.currency) →\n+      fromDecimalAmount(remainder, fractionDigits, this.currency)\n+  }\n+\n+  def % (other: HighPrecisionMoney)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this.remainder(other)\n+\n+  def % (m: Money)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this.remainder(m.toHighPrecisionMoney(fractionDigits))\n+\n+  def % (other: BigDecimal)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this.remainder(fromDecimalAmount(other, this.fractionDigits, this.currency))\n+\n+  def remainder(other: HighPrecisionMoney)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    calc(this, other, _ remainder _)\n+\n+  def remainder(other: BigDecimal)(implicit mode: RoundingMode): HighPrecisionMoney =\n+    this.remainder(fromDecimalAmount(other, this.fractionDigits, this.currency))\n+\n+  def unary_- = fromDecimalAmount(-this.amount, this.fractionDigits, this.currency)(BigDecimal.RoundingMode.UNNECESSARY)\n+\n+  /**\n+   * Partitions this amount of money into several parts where the size of the individual\n+   * parts are defined by the given ratios. The partitioning takes care of not losing or gaining\n+   * any money by distributing any remaining \"cents\" evenly across the partitions.\n+   *\n+   * <p>Example: (0.05 EUR) partition (3,7) == Seq(0.02 EUR, 0.03 EUR)</p>\n+   */\n+  def partition(ratios: Int*)(implicit mode: RoundingMode): Seq[HighPrecisionMoney] = {\n+    val total = ratios.sum\n+    val factor = BigDecimal(1) / BigDecimal(10).pow(fractionDigits)\n+    val amountAsInt = (this.amount / factor).toBigInt\n+    val portionAmounts = ratios.map(amountAsInt * _ / total)\n+    var remainder = portionAmounts.foldLeft(amountAsInt)(_ - _)\n+\n+    portionAmounts.map { portionAmount ⇒\n+      remainder -= 1\n+\n+      fromDecimalAmount(BigDecimal(portionAmount + (if (remainder >= 0) 1 else 0)) * factor, this.fractionDigits, this.currency)\n+    }\n+  }\n+\n+  def toMoneyWithPrecisionLoss: Money =\n+    Money.fromCentAmount(this.centAmount, currency)\n+\n+  def compare(other: Money): Int = {\n+    BaseMoney.requireSameCurrency(this, other)\n+\n+    this.amount compare other.amount\n+  }\n+\n+  override def toString = (\"%.\" + this.fractionDigits + \"f %s\")\n+    .format(this.amount, this.currency.getSymbol)\n+\n+  def toString(nf: NumberFormat) = {\n+    require(nf.getCurrency eq this.currency)\n+\n+    nf.format(this.amount.doubleValue) + \" \" + this.currency.getSymbol\n+  }\n+}\n+\n+object HighPrecisionMoney {\n+  final implicit class HighPrecisionMoneyNotation(val amount: BigDecimal) extends AnyVal {\n+    def EUR = HighPrecisionMoney.EUR(amount)\n+    def USD = HighPrecisionMoney.USD(amount)\n+    def GBP = HighPrecisionMoney.GBP(amount)\n+    def JPY = HighPrecisionMoney.JPY(amount)\n+\n+    def EUR_PRECISE(precision: Int) = HighPrecisionMoney.EUR(amount, Some(precision))\n+    def USD_PRECISE(precision: Int) = HighPrecisionMoney.EUR(amount, Some(precision))\n+    def GBP_PRECISE(precision: Int) = HighPrecisionMoney.EUR(amount, Some(precision))\n+    def JPY_PRECISE(precision: Int) = HighPrecisionMoney.EUR(amount, Some(precision))\n+  }\n+\n+  def EUR(amount: BigDecimal, precision: Option[Int] = None) = simpleValueMeantToBeUsedOnlyInTests(amount, \"EUR\", precision)\n+  def USD(amount: BigDecimal, precision: Option[Int] = None) = simpleValueMeantToBeUsedOnlyInTests(amount, \"USD\", precision)\n+  def GBP(amount: BigDecimal, precision: Option[Int] = None) = simpleValueMeantToBeUsedOnlyInTests(amount, \"GBP\", precision)\n+  def JPY(amount: BigDecimal, precision: Option[Int] = None) = simpleValueMeantToBeUsedOnlyInTests(amount, \"JPY\", precision)\n+\n+  val TypeName = \"preciseAmount\"\n+\n+  private def simpleValueMeantToBeUsedOnlyInTests(amount: BigDecimal, currencyCode: String, precision: Option[Int] = None): HighPrecisionMoney = {\n+    val currency = Currency.getInstance(currencyCode)\n+\n+    val fractionDigits = precision.getOrElse(currency.getDefaultFractionDigits)\n+\n+    fromDecimalAmount(amount, fractionDigits, currency)(BigDecimal.RoundingMode.HALF_EVEN)\n+  }\n+\n+  def roundToCents(amount: BigDecimal, currency: Currency)(implicit mode: RoundingMode): Long =\n+    (amount.setScale(currency.getDefaultFractionDigits, mode) / centFactor(currency)).toLong\n+\n+  def sameScale(m1: HighPrecisionMoney, m2: HighPrecisionMoney): (BigDecimal, BigDecimal, Int) = {\n+    val newFractionDigits = math.max(m1.fractionDigits, m2.fractionDigits)\n+\n+    def scale(m: HighPrecisionMoney, s: Int) =\n+      if (m.fractionDigits < s) m.amount.setScale(s)\n+      else if (m.fractionDigits == s) m.amount\n+      else throw new IllegalStateException(\"Downscale is not allowed/expected at this point!\")\n+\n+    (scale(m1, newFractionDigits), scale(m2, newFractionDigits), newFractionDigits)\n+  }\n+\n+  def calc(m1: HighPrecisionMoney, m2: HighPrecisionMoney, fn: (BigDecimal, BigDecimal) ⇒ BigDecimal)(implicit mode: RoundingMode) = {\n+    BaseMoney.requireSameCurrency(m1, m2)\n+\n+    val (a1, a2, fd) = sameScale(m1, m2)\n+\n+    fromDecimalAmount(fn(a1, a2), fd, m1.currency)\n+  }\n+\n+  def factor(fractionDigits: Int) = BigDecimal(1) / BigDecimal(10).pow(fractionDigits)\n+  def centFactor(currency: Currency) = factor(currency.getDefaultFractionDigits)\n+\n+  def fromDecimalAmount(amount: BigDecimal, fractionDigits: Int, currency: Currency)(implicit mode: RoundingMode) = {\n+    val scaledAmount = amount.setScale(fractionDigits, mode)\n+\n+    HighPrecisionMoney(scaledAmount, fractionDigits, roundToCents(scaledAmount, currency), currency)\n+  }\n+\n+  def fromCentAmount(centAmount: Long, fractionDigits: Int, currency: Currency) = {\n+    val amount = BigDecimal(centAmount) * centFactor(currency)\n+\n+    HighPrecisionMoney(amount.setScale(fractionDigits, BigDecimal.RoundingMode.UNNECESSARY), fractionDigits, centAmount, currency)\n+  }\n+\n+  def zero(fractionDigits: Int, currency: Currency) =\n+    fromCentAmount(0L, fractionDigits, currency)\n+\n+  /* centAmount provides an escape hatch in cases where the default rounding mode is not applicable */\n+  def fromPreciseAmount(preciseAmount: Long, fractionDigits: Int, currency: Currency, centAmount: Option[Long]) = {","path":"util/src/main/scala/Money.scala","position":445,"original_position":445,"commit_id":"9a7a0b19a3a68ea4ae1a9e49c16045936625d1d2","original_commit_id":"9a7a0b19a3a68ea4ae1a9e49c16045936625d1d2","user":{"login":"cneijenhuis","id":2638512,"avatar_url":"https://avatars3.githubusercontent.com/u/2638512?v=4","gravatar_id":"","url":"https://api.github.com/users/cneijenhuis","html_url":"https://github.com/cneijenhuis","followers_url":"https://api.github.com/users/cneijenhuis/followers","following_url":"https://api.github.com/users/cneijenhuis/following{/other_user}","gists_url":"https://api.github.com/users/cneijenhuis/gists{/gist_id}","starred_url":"https://api.github.com/users/cneijenhuis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cneijenhuis/subscriptions","organizations_url":"https://api.github.com/users/cneijenhuis/orgs","repos_url":"https://api.github.com/users/cneijenhuis/repos","events_url":"https://api.github.com/users/cneijenhuis/events{/privacy}","received_events_url":"https://api.github.com/users/cneijenhuis/received_events","type":"User","site_admin":false},"body":"I don't really understand the comment above. At least, shouldn't `centAmount` default to `None`?","created_at":"2018-02-27T12:05:47Z","updated_at":"2018-02-27T12:07:48Z","html_url":"https://github.com/sphereio/sphere-scala-libs/pull/34#discussion_r170900564","pull_request_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/comments/170900564"},"html":{"href":"https://github.com/sphereio/sphere-scala-libs/pull/34#discussion_r170900564"},"pull_request":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34"}}},"pull_request":{"url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34","id":171611260,"html_url":"https://github.com/sphereio/sphere-scala-libs/pull/34","diff_url":"https://github.com/sphereio/sphere-scala-libs/pull/34.diff","patch_url":"https://github.com/sphereio/sphere-scala-libs/pull/34.patch","issue_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/34","number":34,"state":"open","locked":false,"title":"High precision money","user":{"login":"msvaljek","id":36041566,"avatar_url":"https://avatars3.githubusercontent.com/u/36041566?v=4","gravatar_id":"","url":"https://api.github.com/users/msvaljek","html_url":"https://github.com/msvaljek","followers_url":"https://api.github.com/users/msvaljek/followers","following_url":"https://api.github.com/users/msvaljek/following{/other_user}","gists_url":"https://api.github.com/users/msvaljek/gists{/gist_id}","starred_url":"https://api.github.com/users/msvaljek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/msvaljek/subscriptions","organizations_url":"https://api.github.com/users/msvaljek/orgs","repos_url":"https://api.github.com/users/msvaljek/repos","events_url":"https://api.github.com/users/msvaljek/events{/privacy}","received_events_url":"https://api.github.com/users/msvaljek/received_events","type":"User","site_admin":false},"body":"@sphereio/backend please review\r\n\r\nThis might be a bit of an early PR, stuff still might change, but no harm in already starting the discussions.\r\n\r\n### High precision money support\r\n\r\nNew trait was created `BaseMoney`, existing `Money` extends it. The type that will support the high precision money is `HighPrecisionMoney`, it also extends the `BaseMoney`.\r\n\r\nMain idea is to keep the two types relatively compatible, so this is how the usual money looked like:\r\n```\r\n{\r\n    \"currencyCode\": \"USD\",\r\n    \"centAmount\": 2380\r\n}\r\n```\r\nIf this information would be sent by the client, it's treated as 'Money` i.e. the type is 'centAmount`, basically if the above provided JSON would be sent to server internally it would be treated as:\r\n```\r\n{\r\n    \"type\": \"centAmount\",\r\n    \"currencyCode\": \"USD\",\r\n    \"centAmount\": 2380,\r\n    \"fractionDigits\": 2\r\n}\r\n```\r\n\r\nNew format will be returned to the client and the clients should remain unaffected since `currencyCode` and `centAmount` are still there. Additional info is not expected to break the clients when returning this info as result. The same criteria also goes for `HighPrecisionMoney`:\r\n\r\n```\r\n{\r\n    \"type\": \"preciseAmount\",\r\n    \"currencyCode\": \"EUR\",\r\n    \"centAmount\": 6,\r\n    \"preciseAmount\": 550,\r\n    \"fractionDigits\": 4\r\n}\r\n```\r\n\r\nIt still contains all the fields that the clients would expect on response. With time we'll have to think about how to introduce this logic in the client part.\r\n\r\nMoney as such had some places where rounding modes were implicitly set to `HALF_EVEN` when using the operations, all the operations on money (where it makes sense) now expose rounding mode as a implicit parameter.","created_at":"2018-02-27T09:53:18Z","updated_at":"2018-02-27T12:07:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"863766cc466a9c6426991464df34fa98077a6b04","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34/commits","review_comments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34/comments","review_comment_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/comments{/number}","comments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/34/comments","statuses_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/statuses/9a7a0b19a3a68ea4ae1a9e49c16045936625d1d2","head":{"label":"sphereio:high-precision-money","ref":"high-precision-money","sha":"9a7a0b19a3a68ea4ae1a9e49c16045936625d1d2","user":{"login":"sphereio","id":4119130,"avatar_url":"https://avatars1.githubusercontent.com/u/4119130?v=4","gravatar_id":"","url":"https://api.github.com/users/sphereio","html_url":"https://github.com/sphereio","followers_url":"https://api.github.com/users/sphereio/followers","following_url":"https://api.github.com/users/sphereio/following{/other_user}","gists_url":"https://api.github.com/users/sphereio/gists{/gist_id}","starred_url":"https://api.github.com/users/sphereio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sphereio/subscriptions","organizations_url":"https://api.github.com/users/sphereio/orgs","repos_url":"https://api.github.com/users/sphereio/repos","events_url":"https://api.github.com/users/sphereio/events{/privacy}","received_events_url":"https://api.github.com/users/sphereio/received_events","type":"Organization","site_admin":false},"repo":{"id":11254575,"name":"sphere-scala-libs","full_name":"sphereio/sphere-scala-libs","owner":{"login":"sphereio","id":4119130,"avatar_url":"https://avatars1.githubusercontent.com/u/4119130?v=4","gravatar_id":"","url":"https://api.github.com/users/sphereio","html_url":"https://github.com/sphereio","followers_url":"https://api.github.com/users/sphereio/followers","following_url":"https://api.github.com/users/sphereio/following{/other_user}","gists_url":"https://api.github.com/users/sphereio/gists{/gist_id}","starred_url":"https://api.github.com/users/sphereio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sphereio/subscriptions","organizations_url":"https://api.github.com/users/sphereio/orgs","repos_url":"https://api.github.com/users/sphereio/repos","events_url":"https://api.github.com/users/sphereio/events{/privacy}","received_events_url":"https://api.github.com/users/sphereio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/sphereio/sphere-scala-libs","description":null,"fork":false,"url":"https://api.github.com/repos/sphereio/sphere-scala-libs","forks_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/forks","keys_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/teams","hooks_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/hooks","issue_events_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/events{/number}","events_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/events","assignees_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/assignees{/user}","branches_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/branches{/branch}","tags_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/tags","blobs_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/refs{/sha}","trees_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/statuses/{sha}","languages_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/languages","stargazers_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/stargazers","contributors_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/contributors","subscribers_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/subscribers","subscription_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/subscription","commits_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/commits{/sha}","git_commits_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/commits{/sha}","comments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/comments{/number}","issue_comment_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/comments{/number}","contents_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/contents/{+path}","compare_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/merges","archive_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/downloads","issues_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues{/number}","pulls_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls{/number}","milestones_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/milestones{/number}","notifications_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/labels{/name}","releases_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/releases{/id}","deployments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/deployments","created_at":"2013-07-08T13:09:48Z","updated_at":"2018-02-27T11:45:38Z","pushed_at":"2018-02-27T09:53:19Z","git_url":"git://github.com/sphereio/sphere-scala-libs.git","ssh_url":"git@github.com:sphereio/sphere-scala-libs.git","clone_url":"https://github.com/sphereio/sphere-scala-libs.git","svn_url":"https://github.com/sphereio/sphere-scala-libs","homepage":null,"size":289,"stargazers_count":16,"watchers_count":16,"language":"Scala","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":7,"open_issues":5,"watchers":16,"default_branch":"master"}},"base":{"label":"sphereio:master","ref":"master","sha":"c33d2dee4585946e758d9750fe4191308d700852","user":{"login":"sphereio","id":4119130,"avatar_url":"https://avatars1.githubusercontent.com/u/4119130?v=4","gravatar_id":"","url":"https://api.github.com/users/sphereio","html_url":"https://github.com/sphereio","followers_url":"https://api.github.com/users/sphereio/followers","following_url":"https://api.github.com/users/sphereio/following{/other_user}","gists_url":"https://api.github.com/users/sphereio/gists{/gist_id}","starred_url":"https://api.github.com/users/sphereio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sphereio/subscriptions","organizations_url":"https://api.github.com/users/sphereio/orgs","repos_url":"https://api.github.com/users/sphereio/repos","events_url":"https://api.github.com/users/sphereio/events{/privacy}","received_events_url":"https://api.github.com/users/sphereio/received_events","type":"Organization","site_admin":false},"repo":{"id":11254575,"name":"sphere-scala-libs","full_name":"sphereio/sphere-scala-libs","owner":{"login":"sphereio","id":4119130,"avatar_url":"https://avatars1.githubusercontent.com/u/4119130?v=4","gravatar_id":"","url":"https://api.github.com/users/sphereio","html_url":"https://github.com/sphereio","followers_url":"https://api.github.com/users/sphereio/followers","following_url":"https://api.github.com/users/sphereio/following{/other_user}","gists_url":"https://api.github.com/users/sphereio/gists{/gist_id}","starred_url":"https://api.github.com/users/sphereio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sphereio/subscriptions","organizations_url":"https://api.github.com/users/sphereio/orgs","repos_url":"https://api.github.com/users/sphereio/repos","events_url":"https://api.github.com/users/sphereio/events{/privacy}","received_events_url":"https://api.github.com/users/sphereio/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/sphereio/sphere-scala-libs","description":null,"fork":false,"url":"https://api.github.com/repos/sphereio/sphere-scala-libs","forks_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/forks","keys_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/teams","hooks_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/hooks","issue_events_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/events{/number}","events_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/events","assignees_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/assignees{/user}","branches_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/branches{/branch}","tags_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/tags","blobs_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/refs{/sha}","trees_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/statuses/{sha}","languages_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/languages","stargazers_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/stargazers","contributors_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/contributors","subscribers_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/subscribers","subscription_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/subscription","commits_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/commits{/sha}","git_commits_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/git/commits{/sha}","comments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/comments{/number}","issue_comment_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/comments{/number}","contents_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/contents/{+path}","compare_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/merges","archive_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/downloads","issues_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues{/number}","pulls_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls{/number}","milestones_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/milestones{/number}","notifications_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/labels{/name}","releases_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/releases{/id}","deployments_url":"https://api.github.com/repos/sphereio/sphere-scala-libs/deployments","created_at":"2013-07-08T13:09:48Z","updated_at":"2018-02-27T11:45:38Z","pushed_at":"2018-02-27T09:53:19Z","git_url":"git://github.com/sphereio/sphere-scala-libs.git","ssh_url":"git@github.com:sphereio/sphere-scala-libs.git","clone_url":"https://github.com/sphereio/sphere-scala-libs.git","svn_url":"https://github.com/sphereio/sphere-scala-libs","homepage":null,"size":289,"stargazers_count":16,"watchers_count":16,"language":"Scala","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"archived":false,"open_issues_count":5,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":7,"open_issues":5,"watchers":16,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34"},"html":{"href":"https://github.com/sphereio/sphere-scala-libs/pull/34"},"issue":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/34"},"comments":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/issues/34/comments"},"review_comments":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34/comments"},"review_comment":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/pulls/34/commits"},"statuses":{"href":"https://api.github.com/repos/sphereio/sphere-scala-libs/statuses/9a7a0b19a3a68ea4ae1a9e49c16045936625d1d2"}},"author_association":"NONE"}}
{"actor":{"display_login":"cneijenhuis"}}