All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iheart.thomas.analysis.KPIStats.scala Maven / Gradle / Ivy

package com.iheart.thomas
package analysis

import breeze.stats.meanAndVariance.MeanAndVariance
import cats.UnorderedFoldable
import cats.kernel.{CommutativeMonoid, Monoid}
import cats.implicits._
import henkan.convert.Syntax._

sealed trait KPIStats

case class Conversions(
    converted: Long,
    total: Long)
    extends KPIStats {
  def rate = converted.toDouble / total.toDouble

  def sampleSize: Long = total

  override def toString: String =
    s"Conversions(converted: $converted, total: $total, rate: ${"%.2f".format(rate * 100)}%)"
}

object Conversions {
  implicit val monoidInstance: Monoid[Conversions] = new Monoid[Conversions] {
    def empty: Conversions = Conversions(0, 0)

    def combine(
        x: Conversions,
        y: Conversions
      ): Conversions =
      Conversions(
        x.converted + y.converted,
        x.total + y.total
      )
  }

  def apply[C[_]: UnorderedFoldable](
      events: C[ConversionEvent]
    ): Conversions = {
    val converted = events.count(identity)
    val init = events.size - converted
    Conversions(converted, init)
  }
}

case class PerUserSamplesLnSummary(
    mean: Double,
    variance: Double,
    count: Long)
    extends KPIStats

object PerUserSamplesLnSummary {
  def fromSamples(samples: PerUserSamples): PerUserSamplesLnSummary =
    samples.lnSummary

  def apply(samples: PerUserSamples): PerUserSamplesLnSummary = fromSamples(samples)

  implicit val instances: CommutativeMonoid[PerUserSamplesLnSummary] =
    new CommutativeMonoid[PerUserSamplesLnSummary] {
      def empty: PerUserSamplesLnSummary = PerUserSamplesLnSummary(0d, 0d, 0L)

      def combine(
          x: PerUserSamplesLnSummary,
          y: PerUserSamplesLnSummary
        ): PerUserSamplesLnSummary =
        (x.to[MeanAndVariance]() + y.to[MeanAndVariance]())
          .to[PerUserSamplesLnSummary]()
    }
}

trait Aggregation[Event, KS <: KPIStats] {
  def apply[C[_]: UnorderedFoldable](events: C[Event]): KS
}

object Aggregation {
  implicit val conversionsAggregation: Aggregation[ConversionEvent, Conversions] =
    new Aggregation[ConversionEvent, Conversions] {
      def apply[C[_]: UnorderedFoldable](events: C[ConversionEvent]) =
        Conversions(events)
    }

  implicit val accumulativeAggregation
      : Aggregation[PerUserSamples, PerUserSamplesLnSummary] =
    new Aggregation[PerUserSamples, PerUserSamplesLnSummary] {
      def apply[C[_]: UnorderedFoldable](events: C[PerUserSamples]) =
        events.unorderedFold.lnSummary
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy