Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
djnzx committed Sep 2, 2023
1 parent cd6e42f commit 39975e3
Show file tree
Hide file tree
Showing 13 changed files with 423 additions and 37 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,25 @@ I thought I knew Scala...
- cats effects 3. recap
- week 2
- tapir 0.19.3
- typelevel deep dive again
- cats
- effects
- fs2
- doobie
- http4s
- circe
- shapeless
- kafka streams processing
- youtube API

### 2023 notes
- typelevel deep dive again
- cats
- effects
- fs2
- doobie
- http4s
- circe
- shapeless
- kafka streams processing
-
15 changes: 15 additions & 0 deletions algorithms/src/main/scala/cry/Playground.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ class PlaygroundSpec extends AnyFunSpec with Matchers with ScalaCheckPropertyChe
1 shouldEqual 1
}

it("nested forall count") {
var c = 0
forAll { s1: String => // 10 times

forAll{ s2: String => // 10 times
c += 1
val s3 = s1 + s2
s3.length should be >= 0
}

}
pprint.pprintln(c) // 10x10 = 100 times
}


it("2") {

forAll { (s1: String, s2: String) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package scalacheck.extrasyntax

import org.scalacheck.{Arbitrary, Gen}

trait ArbitraryFromGen {

implicit def genArbitrary[A](implicit gen: Gen[A]): Arbitrary[A] = Arbitrary(gen)

}
28 changes: 28 additions & 0 deletions ce3/src/main/scala/scalacheck/extrasyntax/GenExtraSyntax.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package scalacheck.extrasyntax

import org.scalacheck.Gen

trait GenExtraSyntax {

private object impl {
def const[A](ga: Gen[A]): Gen[A] = Gen.const(ga.sample.get)
}

implicit class GenOps2[A](ga: Gen[A]) {

/** make Any generator constant TO ONE VALUE */
def const: Gen[A] = impl.const(ga)

/** make CONSTANT LIST from Any generator */
def constListOfN(n: Int): Gen[List[A]] = impl.const(Gen.listOfN(n, ga))

/** take random element from {{{Gen[Seq[A]]}}} and produce {{{Gen[A]}}} */
def oneOf[B](implicit ev: A <:< Seq[B]): Gen[B] = ga.map(ev).flatMap(x => Gen.oneOf(x))

def notPresentIn(as: Seq[A]): Gen[A] = ga.retryUntil(a => !as.contains(a))

def notPresentIn(gas: Gen[Seq[A]]): Gen[A] = notPresentIn(gas.sample.get)

}

}
70 changes: 70 additions & 0 deletions ce3/src/main/scala/scalacheck/extrasyntax/GenExtraSyntaxTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package scalacheck.extrasyntax

import org.scalacheck.Gen
import org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks

class GenExtraSyntaxTest extends BootstrapFunSuite with ScalaCheckDrivenPropertyChecks with ArbitraryFromGen with GenExtraSyntax {

override implicit val generatorDrivenConfig: PropertyCheckConfiguration = PropertyCheckConfiguration(minSuccessful = 25)

val tenCharsId = Gen.listOfN(10, Gen.alphaChar).map(_.mkString)

test(".const syntax provides always constant value") {
implicit val g: Gen[String] = tenCharsId.const

forAll { (x: String) =>
pprint.pprintln(x)
x shouldBe g.sample.value
}
}

test(".constListOfN(...) syntax provides always constant value of a List[A]") {
implicit val g: Gen[List[String]] = tenCharsId.constListOfN(5)

forAll { (x: List[String]) =>
pprint.pprintln(x)
x shouldBe g.sample.value
}
}

test(".oneOf syntax provides always constant value from the Gen[Geq[A]] given") {
// always the same list
val gs: Gen[List[String]] = tenCharsId.constListOfN(5)
// element from the list
implicit val g: Gen[String] = gs.oneOf

forAll { (x: String) =>
pprint.pprintln(x)
gs.sample.value should contain(x)
}

pprint.pprintln(gs.sample.value)
}

test(".notPresentIn - allows to reuse generator, but with a guarantee not have a duplicate one") {

/** Int: 1..10 */
val g0: Gen[Int] = Gen.choose(1, 10)

/** List[Int] max length = 9 */
val g1: Gen[List[Int]] = Gen.listOfN(10, g0).map(_.distinct.sorted)

/** Int: 1..10 but never in the list */
val g2 = g0.notPresentIn _

implicit val gtuple: Gen[(List[Int], Int)] = for {
xs <- g1 // list
x <- g2(xs) // element not presented in the list
} yield (xs, x)

forAll { t: (List[Int], Int) =>
t match {
case (xs, x) =>
pprint.pprintln((xs, x))
xs shouldNot contain(x)
}
}

}

}
89 changes: 89 additions & 0 deletions typesafe/src/main/scala/slickvt/Impl.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package slickvt

import akka.NotUsed
import akka.stream.scaladsl.Source
import model._
import slick.jdbc.PostgresProfile.api.{Tag => _, _}
import slick.lifted.Rep
import slickvt.model.TagFilter.{ExcludesOnly, IncludesAndExcludes, IncludesOnly}
import slickvt.model.TargetStrategies._

trait Impl extends StreamOps with SlickStreamingQueryOps {

private def negateBy(strategy: TargetStrategy): Rep[Boolean] => Rep[Boolean] =
if (strategy == Exclude) !_ else identity

private def whereCountry(query: ProfileTable, country: CountryFilter) = country match {
case CountryFilter(Seq(), _) => query.country.isDefined
case CountryFilter(countries, strategy) => query.country
.map { country => negateBy(strategy)(country inSet countries) }
.getOrElse(LiteralColumn(false))
}

private def whereAffiliate(profiles: ProfileTable, affiliate: AffiliateFilter) = affiliate match {
case AffiliateFilter(Seq(), _) => LiteralColumn(true)
case AffiliateFilter(affiliates, strategy) => profiles.affiliateId
.map { id => negateBy(strategy)(id inSet affiliates) }
.getOrElse(LiteralColumn(strategy == Exclude))
}

private def wherePlayerUuids(profiles: ProfileTable, playerUuids: PlayerUuidFilter) =
profiles.playerUUID inSet playerUuids.includeUuids

def qCond(p: Boolean)(r: Rep[Boolean]): Rep[Boolean] = if (p) r else !r

private def mkTagWhereClause(rqTags: Seq[PTag])(tags: TagTable): Rep[Boolean] =
rqTags.groupMap(_.rank)(_.tagId)
.map { case (rank, tagIds) => (tags.rank === rank) && (tags.tagId inSet tagIds) }
.reduce(_ || _)

def mkProfilesFilter(request: RQuery) =
ProfileTable.profiles // case class RQuery(
.filter(_.brandId === request.brandId) // brandId: String,
.filter(profiles => qCond(request.isTest)(profiles.playerUUID.like(TestPattern))) // isTest: Boolean = false
.filterOpt(request.affiliateFilter)(whereAffiliate) // affiliateFilter: Option[AffiliateFilter] = None
.filterOpt(request.countryFilter)(whereCountry) // countryFilter: Option[CountryFilter] = None
.filterOpt(request.playerUuidFilter)(wherePlayerUuids) // playerUuidFilter: Option[PlayerUuidFilter] = None
.filterOpt(request.playerId)(_.playerUUID === _) // playerId: Option[String] = None

private def mkTagsFilter(request: RQuery): Query[TagTable, Tag, Seq] =
TagTable.tags
.filter(_.brandId === request.brandId)
.filterOpt(request.playerUuidFilter)(_.playerUUID inSet _.includeUuids)
.filterOpt(request.playerId)(_.playerUUID === _)


private def doFindProfilesWithTags(request: RQuery) = {
val profilesFiltered = mkProfilesFilter(request)
val tagsFiltered = mkTagsFilter(request)

val tagsFiltered2 = request.tagFilter match {
case Some(IncludesOnly(includes)) =>
tagsFiltered
.filter(mkTagWhereClause(includes))
case Some(ExcludesOnly(excludes)) =>
tagsFiltered
.filterNot(mkTagWhereClause(excludes))
case Some(IncludesAndExcludes(includes, excludes)) =>
tagsFiltered
.filter(mkTagWhereClause(includes))
.filterNot(mkTagWhereClause(excludes))
case _ =>
tagsFiltered
}

profilesFiltered
.joinLeft(tagsFiltered2).on(_.playerUUID === _.playerUUID)
.map{ case (p, ots) => p -> ots.map(t => t.tagId -> t.rank)}
.sortBy { case (p, _) => p.playerUUID }
.result
}

def findProfilesWithTagsSource(request: RQuery) = {
val s = runStream(doFindProfilesWithTags(request))

regroupSequentialAfterJoin(s)(_._1)(_._2)
.map { case (p, ts) => p -> ts.flatten }
}

}
71 changes: 34 additions & 37 deletions typesafe/src/main/scala/slickvt/Launcher.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,50 @@ object Launcher extends App with SlickBase {

val players = Seq(
"PLAYER-8d299950-9a29-4bee-b53f-b544ad7f8d37",
"PLAYER-6b6ff783-347d-4c42-a85b-aabda3774a99"
"PLAYER-6b6ff783-347d-4c42-a85b-aabda3774a99",
"PLAYER-c04a1454-da67-4b27-8fb3-677564505d17"
)

/**
* select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* x3."tag_id",x3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date"
* from
* "profile" x2
* left outer join "tag" x3 on (x2."player_uuid" = x3."player_uuid")
*/
/** select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* x3."tag_id",x3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date"
* from
* "profile" x2
* left outer join "tag" x3 on (x2."player_uuid" = x3."player_uuid")
*/
// left outer join
val q1: Query[(ProfileTable, Rep[Option[TagTable]]), (Profile, Option[Tag]), Seq] = ProfileTable.profiles
val q1 = // : Query[(ProfileTable, Rep[Option[TagTable]]), (Profile, Option[Tag]), Seq] =
// ================ ===========
.joinLeft(TagTable.tags)
.on(_.playerUUID === _.playerUUID)
.filter{case(p,_) => p.playerUUID inSet(players)}

/**
* select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* 3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date"
* from "profile" x2,
* "tag" x3
* where
* x2."player_uuid" = x3."player_uuid"
*/
ProfileTable.profiles
.joinLeft(TagTable.tags)
.on(_.playerUUID === _.playerUUID)
.filter { case (p, _) => p.playerUUID inSet players }
.map { case (p, t) => p.playerUUID -> t.map(_.tagId) }

/** select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* 3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date"
* from "profile" x2,
* "tag" x3
* where
* x2."player_uuid" = x3."player_uuid"
*/
// join
val q2: Query[(ProfileTable, TagTable), (Profile, Tag), Seq] = ProfileTable.profiles
// ========= ===
.join(TagTable.tags)
.on(_.playerUUID === _.playerUUID)

/**
* select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* x3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date" +
* from
* "profile" x2,
* "tag" x3
* where
* x2."player_uuid" = x3."player_uuid"
*/
val q: Query[(ProfileTable, TagTable), (Profile, Tag), Seq] = for {
/** select
* x2."brand_id", x2."player_uuid", x2."country", x2."affiliate_id", x2."registration_date",
* x3."brand_id", x3."player_uuid", x3."tag_id", x3."rank", x3."creation_date" +
* from
* "profile" x2,
* "tag" x3
* where
* x2."player_uuid" = x3."player_uuid"
*/
val q3: Query[(ProfileTable, TagTable), (Profile, Tag), Seq] = for {
// ======== ===
p <- ProfileTable.profiles
t <- TagTable.tags
Expand All @@ -59,7 +59,4 @@ object Launcher extends App with SlickBase {
q1.run
.foreach(x => pprint.pprintln(x))

// q.stream
// .runForeach()

}
31 changes: 31 additions & 0 deletions typesafe/src/main/scala/slickvt/Launcher2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package slickvt

import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
import cats.implicits._
import slick.jdbc.PostgresProfile.api.{Tag => _, _}
import slickvt.model._

object Launcher2 extends App with Impl {

implicit val system = ActorSystem()
implicit val mat = ActorMaterializer()

val rq = RQuery(brandId = "bccashgames",
tagFilter = TagFilter(
includeTags = Seq(
PTag("TAG-completed",0),
PTag("TAG-promo_test",0),
PTag("TAG-testcampaign",0),
),
excludeTags = Seq(),
).some,
// playerId = "PLAYER-fea4a1cf-c83d-40dc-803a-60f46a813390".some
)

findProfilesWithTagsSource(rq)
.filter{case(_,ts)=>ts.size > 1}
// .take(1)
.runForeach(x => pprint.pprintln(x))

}
7 changes: 7 additions & 0 deletions typesafe/src/main/scala/slickvt/SlickBase.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package slickvt


import akka.actor.ActorSystem
import akka.stream.scaladsl.Source
import slick.dbio.{DBIOAction, Streaming}
import slick.jdbc.PostgresProfile.api._
Expand All @@ -24,4 +25,10 @@ trait SlickBase {
def stream = stream0(q.result)
}

implicit class DbioOps[T](dbio: DBIOAction[_, Streaming[T], Nothing]) {
def stream = stream0(dbio)
}

// implicit val sys = ActorSystem()
// implicit val ec = sys.dispatcher
}
Loading

0 comments on commit 39975e3

Please sign in to comment.