<commit_before>package provingground.learning

import provingground._, HoTT._
import monix.eval._, monix.tail._
import monix.execution.Scheduler.Implicits.global
import shapeless._
import scala.concurrent.Future
import scala.collection.mutable.ArrayBuffer
import scala.collection.SeqView
import scala.util.Try

/* Code for mixed autonomous and interactive running.
 * We can interact by posting various objects.
 * There are also bots that post in reaction to other posts, in general using the results of queries.
 * The behaviour of a post is largely determined by its (scala) type.
 * The type `W` (for web) will handle posting and querying based on posts (this is implemented using typeclasses with `W`)
 */

/**
 * Typeclass for being able to post with content type P in W
 */
trait Postable[P, W, ID] {
  def post(content: P, web: W, pred: Set[ID]): Future[ID]
}

/**
  * Typeclass for being able to query W for type Q
  */
trait Queryable[U, W] {
  def get(web: W, predicate: U => Boolean): Future[U]
}

object Queryable{
  /**
    * a simple query, with result blocking and no predicate
    *
    * @param func the query function
    * @return typeclass implementation based on `func`
    */
  def simple[U, W](func: W => U) = new Queryable[U, W] {
    def get(web: W, predicate: U => Boolean): Future[U] = 
      Future(func(web))
  }

  /**
    * querying for objects of a type, as a view
    *
    * @param pw postability of `P`, needed for history
    * @param ph post history of `P` from `W`
    * @return implementation of querying typeclass
    */
  implicit def allView[P, W, ID](implicit pw: Postable[P, W, ID], ph: PostHistory[W, ID]) : Queryable[SeqView[P, Seq[_]], W] = 
    new Queryable[SeqView[P, Seq[_]], W] {
      def get(web: W, predicate: SeqView[P, Seq[_]] => Boolean): Future[SeqView[P, Seq[_]]] = 
       Future{ ph.allPosts(web).filter(_.pw == pw).map{_.asInstanceOf[P]}}
    }
    

}
/**
 * Typeclass for being able to query W for a vector of elements of type Q at an index
 */ 
trait LocalQueryable[U, W, ID] {
  def getAt(web: W, id: ID, predicate: U => Boolean): Future[Vector[U]]
}

/** 
  * Looking up an answer to a query for `U` from posts of type `P`
  * meant for querying for the latest post etc.
  *
  * @param func transformation of the content of the post
  * @param pw postability
  */
case class AnswerFromPost[P, U, W, ID](func: P => U)(
  implicit pw: Postable[P, W, ID]
) {
def fromPost[Q](data: PostData[Q, W, ID]) : Option[U] =
  if (pw == data.pw) Some(func(data.content.asInstanceOf[P])) else None
}

/**
  * Queries answered by taking the latest out of possibly many choices of posts to be looked up and transformed.
  *
  * @param answers various ways in which the query can be answered
  * @param h the history
  */
case class LatestAnswer[Q, W, ID](
  answers: Seq[AnswerFromPost[_, Q, W, ID]]
)(implicit h: PostHistory[W, ID])
  extends LocalQueryable[Q, W, ID] {
    def getAt(web: W, id: ID, predicate: Q => Boolean): Future[Vector[Q]] = Future{
      def answer: PostData[_, W, ID] => Option[Q] = 
        (pd) => answers.flatMap(ans => ans.fromPost(pd)).filter(predicate).headOption
      h.latestAnswers(web, id, answer).toVector
    }
  }


trait FallBackLookups{
  /**
    * default implementation of lookup for stuff that can be posted given a post-history implementation,
    * where we look fot the latest post.
    *
    * @param qw postability of `Q`
    * @param ph post history
    * @return implementation of query lookup
    */
  implicit   def lookupLatest[Q, W, ID](implicit qw: Postable[Q, W, ID], ph: PostHistory[W, ID]) : LocalQueryable[Q, W, ID] = 
  LatestAnswer(Seq(AnswerFromPost[Q, Q, W, ID](identity)))

  /**
    * Lookup for the wrapped type `SomePost`, which returns all posts independent of relative position in history.
    *
    * @param pw postability of `P`
    * @param ph post history
    * @return implementation of query lookup
    */
  implicit def somePostQuery[P, W, ID](implicit pw: Postable[P, W, ID], ph: PostHistory[W, ID]) : LocalQueryable[SomePost[P], W, ID] = new LocalQueryable[SomePost[P], W, ID] {
   def getAt(web: W, id: ID, predicate: SomePost[P] => Boolean): Future[Vector[SomePost[P]]] =
     Future{ph.allPosts(web).filter(_.pw == pw).map{post => SomePost(post.content.asInstanceOf[P])}.filter(predicate).toVector
  } 
}
     
}

object LocalQueryable extends FallBackLookups{
  /**
    * Query for an object
    *
    * @param web the web which we query
    * @param predicate property the object must satisfy
    * @param q queryability
    * @return future result of type`Q`
    */
  def query[Q, W](web: W, predicate: Q => Boolean)(implicit q: Queryable[Q, W]):  Future[Q] = q.get(web, predicate)<commit_msg>latest answer helper<commit_after>package provingground.learning

import provingground._, HoTT._
import monix.eval._, monix.tail._
import monix.execution.Scheduler.Implicits.global
import shapeless._
import scala.concurrent.Future
import scala.collection.mutable.ArrayBuffer
import scala.collection.SeqView
import scala.util.Try

/* Code for mixed autonomous and interactive running.
 * We can interact by posting various objects.
 * There are also bots that post in reaction to other posts, in general using the results of queries.
 * The behaviour of a post is largely determined by its (scala) type.
 * The type `W` (for web) will handle posting and querying based on posts (this is implemented using typeclasses with `W`)
 */

/**
 * Typeclass for being able to post with content type P in W
 */
trait Postable[P, W, ID] {
  def post(content: P, web: W, pred: Set[ID]): Future[ID]
}

/**
  * Typeclass for being able to query W for type Q
  */
trait Queryable[U, W] {
  def get(web: W, predicate: U => Boolean): Future[U]
}

object Queryable{
  /**
    * a simple query, with result blocking and no predicate
    *
    * @param func the query function
    * @return typeclass implementation based on `func`
    */
  def simple[U, W](func: W => U) = new Queryable[U, W] {
    def get(web: W, predicate: U => Boolean): Future[U] = 
      Future(func(web))
  }

  /**
    * querying for objects of a type, as a view
    *
    * @param pw postability of `P`, needed for history
    * @param ph post history of `P` from `W`
    * @return implementation of querying typeclass
    */
  implicit def allView[P, W, ID](implicit pw: Postable[P, W, ID], ph: PostHistory[W, ID]) : Queryable[SeqView[P, Seq[_]], W] = 
    new Queryable[SeqView[P, Seq[_]], W] {
      def get(web: W, predicate: SeqView[P, Seq[_]] => Boolean): Future[SeqView[P, Seq[_]]] = 
       Future{ ph.allPosts(web).filter(_.pw == pw).map{_.asInstanceOf[P]}}
    }
    

}
/**
 * Typeclass for being able to query W for a vector of elements of type Q at an index
 */ 
trait LocalQueryable[U, W, ID] {
  def getAt(web: W, id: ID, predicate: U => Boolean): Future[Vector[U]]
}

/** 
  * Looking up an answer to a query for `U` from posts of type `P`
  * meant for querying for the latest post etc.
  *
  * @param func transformation of the content of the post
  * @param pw postability
  */
case class AnswerFromPost[P, U, W, ID](func: P => U)(
  implicit pw: Postable[P, W, ID]
) {
def fromPost[Q](data: PostData[Q, W, ID]) : Option[U] =
  if (pw == data.pw) Some(func(data.content.asInstanceOf[P])) else None
}

/**
  * Queries answered by taking the latest out of possibly many choices of posts to be looked up and transformed.
  *
  * @param answers various ways in which the query can be answered
  * @param h the history
  */
case class LatestAnswer[Q, W, ID](
  answers: Vector[AnswerFromPost[_, Q, W, ID]]
)(implicit h: PostHistory[W, ID])
  extends LocalQueryable[Q, W, ID] {
    def getAt(web: W, id: ID, predicate: Q => Boolean): Future[Vector[Q]] = Future{
      def answer: PostData[_, W, ID] => Option[Q] = 
        (pd) => answers.flatMap(ans => ans.fromPost(pd)).filter(predicate).headOption
      h.latestAnswers(web, id, answer).toVector


    }

    def ||[P](ans: P => Q)(implicit pw: Postable[P, W, ID]) = 
      LatestAnswer(
        answers :+ AnswerFromPost[P, Q, W, ID](ans)
      )
  }


trait FallBackLookups{
  /**
    * default implementation of lookup for stuff that can be posted given a post-history implementation,
    * where we look fot the latest post.
    *
    * @param qw postability of `Q`
    * @param ph post history
    * @return implementation of query lookup
    */
  implicit   def lookupLatest[Q, W, ID](implicit qw: Postable[Q, W, ID], ph: PostHistory[W, ID]) : LocalQueryable[Q, W, ID] = 
  LatestAnswer(Vector(AnswerFromPost[Q, Q, W, ID](identity)))

  /**
    * Lookup for the wrapped type `SomePost`, which returns all posts independent of relative position in history.
    *
    * @param pw postability of `P`
    * @param ph post history
    * @return implementation of query lookup
    */
  implicit def somePostQuery[P, W, ID](implicit pw: Postable[P, W, ID], ph: PostHistory[W, ID]) : LocalQueryable[SomePost[P], W, ID] = new LocalQueryable[SomePost[P], W, ID] {
   def getAt(web: W, id: ID, predicate: SomePost[P] => Boolean): Future[Vector[SomePost[P]]] =
     Future{ph.allPosts(web).filter(_.pw == pw).map{post => SomePost(post.content.asInstanceOf[P])}.filter(predicate).toVector
  } 
}
     
}

object LocalQueryable extends FallBackLookups{
  /**
    * Query for an object
    *
    * @param web the web which we query
    * @param predicate property the object must satisfy
    * @param q queryability
    * @return future result of type`Q`
    */
  def query[Q, W](web: W, predicate: Q => Boolean)(implicit q: Queryable[Q, W]):  Future[Q] = q.get(web, predicate)
{'fraction_non_alphanumeric': 0.1278719201580206, 'fraction_numerical': 0.0, 'mean_word_length': 3.501637810014038, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '527866', 'n_tokens_mistral': 3185, 'n_tokens_neox': 3139, 'n_words': 1117}