<commit_before>// vim: ts=2 sw=2 et
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.debiki.v0

import org.specs._
import org.specs.runner.{ConsoleRunner, JUnit4}
import java.{util => ju}

//class StatsCalcTest extends JUnit4(StatsCalcSpec)
//object StatsCalcTestRunner extends ConsoleRunner(StatsCalcSpec)

//class StatsCalcTest extends SpecificationWithJUnit {
/*
Cannot debug this:
class StatsCalcTest extends SpecificationWithJUnit {
NetBeans says:
  Testsuite: com.debiki.v0.StatsCalcTest
  Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0 sec

  Null Test:         Caused an ERROR
  null
  java.lang.ExceptionInInitializerError
          at java.lang.Class.forName0(Native Method)
          at java.lang.Class.forName(Class.java:169)
  Caused by: java.lang.RuntimeException: Uncompilable source code
   - interface expected here
          at com.debiki.v0.StatsCalcTest.<clinit>(StatsCalcTest.java:2)
*/

//object StatsCalcSpec extends Specification {

object Util {

  /** The upper and lower bounds for an 80% confidence interval for a binomial
   *  proportion, estimated using the Agresti-Coull method.
   *  (The probability the real proportion is higher the value
   *  returned is 90% (not 80%).)
   */
  def binProp80ConfIntAC(trials: Int, prop: Float): (Float, Float) = {
    require(trials >= 0)
    require(prop >= 0f && prop <= 1f)
    var n2 = trials + 4
    var p2 = (prop * trials + 2) / n2
    val root = math.sqrt(p2 * (1-p2) / n2).toFloat
    val z10 = 1.28f
    (p2 - z10 * root, p2 + z10 * root)
  }

  val post = Post(id = "Ca", parent = "root", date = new ju.Date,
                  by = "Someone", ip = "1.2.3.4", text = "test")
  val debate = Debate("test", post :: Nil, Nil)
  val rating_interesting =
        Rating(postId = post.id, by = "?", date = new ju.Date,
               ip = "1.2.3.4", tags = List("interesting"))
  val rating_stupid =
        Rating(postId = post.id, by = "?", date = new ju.Date,
               ip = "2.3.4.5", tags = List("stupid"))
}

import Util._

class PostRatingTest extends SpecificationWithJUnit {

  "For an unrated post, StatsCalc" should {
    "find no statistics" in {
      val calcer = new StatsCalc(debate)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 0
      rating.maxLabelSum must_== 0
      rating.labelStats.size must_== 0
      rating.labelStats.get("interesting") must beNone
      rating.labelStats.get("stupid") must beNone
      rating.labelStats.get("funny") must beNone
    }
  }

  "For a post with one rating, StatsCalc" should {
    "find one rating" in {
      val debate2 = debate + rating_interesting
      val calcer = new StatsCalc(debate2)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 1
      rating.maxLabelSum must_== 1.0f
      rating.labelStats.size must_== 1
      val intresting = rating.labelStats("interesting")
      intresting.sum must_== 1.0f
      intresting.fraction must_== 1.0f
      intresting.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 1, prop = 1f)._1, 0.01f)
      rating.labelStats.get("stupid") must beNone
      rating.labelStats.get("funny") must beNone
    }
  }

  "For a post with two different rating tags, StatsCalc" should {
    "do something sensible" in {
      val debate2 = debate + rating_interesting + rating_stupid
      val calcer = new StatsCalc(debate2)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 2
      rating.maxLabelSum must_== 2.0f
      rating.labelStats.size must_== 2
      val intresting = rating.labelStats("interesting")
      intresting.sum must_== 1.0f
      intresting.fraction must_== 0.5f
      intresting.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 2, prop = 0.5f)._1, 0.01f)
      val stupid = rating.labelStats("stupid")
      stupid.sum must_== 1.0f
      stupid.fraction must_== 0.5f
      stupid.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 2, prop = 0.5f)._1, 0.01f)
      rating.labelStats.get("funny") must beNone
    }
  }
}

class EditLikingTest extends SpecificationWithJUnit {

  val edit = Edit(post.id +"Ea", postId = post.id, date = new ju.Date,
                  by = "?", ip = "1.2.3.4", text = "text")
  val upVote = EditVote(edit.id, "?", "1.2.3.4", new ju.Date, List(edit.id), Nil)
  // Yet another up vote:
  val upVote2 = EditVote("?", "?", "1.2.3.4", new ju.Date, List(edit.id), Nil)<commit_msg>Fix test suite compilation error.<commit_after>// vim: ts=2 sw=2 et
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.debiki.v0

import org.specs._
import org.specs.runner.{ConsoleRunner, JUnit4}
import java.{util => ju}

//class StatsCalcTest extends JUnit4(StatsCalcSpec)
//object StatsCalcTestRunner extends ConsoleRunner(StatsCalcSpec)

//class StatsCalcTest extends SpecificationWithJUnit {
/*
Cannot debug this:
class StatsCalcTest extends SpecificationWithJUnit {
NetBeans says:
  Testsuite: com.debiki.v0.StatsCalcTest
  Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 0 sec

  Null Test:         Caused an ERROR
  null
  java.lang.ExceptionInInitializerError
          at java.lang.Class.forName0(Native Method)
          at java.lang.Class.forName(Class.java:169)
  Caused by: java.lang.RuntimeException: Uncompilable source code
   - interface expected here
          at com.debiki.v0.StatsCalcTest.<clinit>(StatsCalcTest.java:2)
*/

//object StatsCalcSpec extends Specification {

object Util {

  /** The upper and lower bounds for an 80% confidence interval for a binomial
   *  proportion, estimated using the Agresti-Coull method.
   *  (The probability the real proportion is higher the value
   *  returned is 90% (not 80%).)
   */
  def binProp80ConfIntAC(trials: Int, prop: Float): (Float, Float) = {
    require(trials >= 0)
    require(prop >= 0f && prop <= 1f)
    var n2 = trials + 4
    var p2 = (prop * trials + 2) / n2
    val root = math.sqrt(p2 * (1-p2) / n2).toFloat
    val z10 = 1.28f
    (p2 - z10 * root, p2 + z10 * root)
  }

  val post = Post(id = "Ca", parent = "root", date = new ju.Date,
                  by = "Someone", ip = "1.2.3.4", text = "test")
  val debate = Debate("test", post :: Nil, Nil)
  val rating_interesting =
        Rating(postId = post.id, by = "?", date = new ju.Date,
               ip = "1.2.3.4", tags = List("interesting"))
  val rating_stupid =
        Rating(postId = post.id, by = "?", date = new ju.Date,
               ip = "2.3.4.5", tags = List("stupid"))
}

import Util._

class PostRatingTest extends SpecificationWithJUnit {

  "For an unrated post, StatsCalc" should {
    "find no statistics" in {
      val calcer = new StatsCalc(debate)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 0
      rating.maxLabelSum must_== 0
      rating.labelStats.size must_== 0
      rating.labelStats.get("interesting") must beNone
      rating.labelStats.get("stupid") must beNone
      rating.labelStats.get("funny") must beNone
    }
  }

  "For a post with one rating, StatsCalc" should {
    "find one rating" in {
      val debate2 = debate + rating_interesting
      val calcer = new StatsCalc(debate2)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 1
      rating.maxLabelSum must_== 1.0f
      rating.labelStats.size must_== 1
      val intresting = rating.labelStats("interesting")
      intresting.sum must_== 1.0f
      intresting.fraction must_== 1.0f
      intresting.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 1, prop = 1f)._1, 0.01f)
      rating.labelStats.get("stupid") must beNone
      rating.labelStats.get("funny") must beNone
    }
  }

  "For a post with two different rating tags, StatsCalc" should {
    "do something sensible" in {
      val debate2 = debate + rating_interesting + rating_stupid
      val calcer = new StatsCalc(debate2)
      val rating = calcer.scoreFor(post.id)
      rating.ratingCount must_== 2
      rating.maxLabelSum must_== 2.0f
      rating.labelStats.size must_== 2
      val intresting = rating.labelStats("interesting")
      intresting.sum must_== 1.0f
      intresting.fraction must_== 0.5f
      intresting.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 2, prop = 0.5f)._1, 0.01f)
      val stupid = rating.labelStats("stupid")
      stupid.sum must_== 1.0f
      stupid.fraction must_== 0.5f
      stupid.fractionLowerBound must beCloseTo(
          binProp80ConfIntAC(trials = 2, prop = 0.5f)._1, 0.01f)
      rating.labelStats.get("funny") must beNone
    }
  }
}

class EditLikingTest extends SpecificationWithJUnit {

  val edit = Edit(post.id +"Ea", postId = post.id, date = new ju.Date,
                  by = "?", ip = "1.2.3.4", text = "text", desc = "desc")
  val upVote = EditVote(edit.id, "?", "1.2.3.4", new ju.Date, List(edit.id), Nil)
  // Yet another up vote:
  val upVote2 = EditVote("?", "?", "1.2.3.4", new ju.Date, List(edit.id), Nil)
{'fraction_non_alphanumeric': 0.11857315864802379, 'fraction_numerical': 0.0275239458328746, 'mean_word_length': 2.8870346598202823, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 12, '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': '5010259', 'n_tokens_mistral': 3254, 'n_tokens_neox': 3040, 'n_words': 833}