Fix search for Sone elements
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / web / pages / SearchPage.kt
index 7cddc35..76c2341 100644 (file)
@@ -22,14 +22,18 @@ import net.pterodactylus.util.template.TemplateContext
 import net.pterodactylus.util.text.StringEscaper
 import net.pterodactylus.util.text.TextException
 import java.util.concurrent.TimeUnit.MINUTES
+import javax.inject.Inject
 
 /**
  * This page lets the user search for posts and replies that contain certain
  * words.
  */
-class SearchPage @JvmOverloads constructor(template: Template, webInterface: WebInterface, ticker: Ticker = Ticker.systemTicker()):
+class SearchPage(template: Template, webInterface: WebInterface, ticker: Ticker = Ticker.systemTicker()) :
                SoneTemplatePage("search.html", webInterface, template, "Page.Search.Title") {
 
+       @Inject constructor(template: Template, webInterface: WebInterface) :
+                       this(template, webInterface, Ticker.systemTicker())
+
        private val cache: Cache<Iterable<Phrase>, Pagination<Post>> = CacheBuilder.newBuilder().ticker(ticker).expireAfterAccess(5, MINUTES).build()
 
        override fun handleRequest(freenetRequest: FreenetRequest, templateContext: TemplateContext) {
@@ -94,22 +98,19 @@ class SearchPage @JvmOverloads constructor(template: Template, webInterface: Web
                                        .filter { PostReply.FUTURE_REPLY_FILTER.apply(it) }
                                        .map { "${soneNameCache(it.sone)} ${it.text}" }.joinToString(" ", " ")).toLowerCase()
 
+       private fun Iterable<Phrase>.indicesFor(text: String, predicate: (Phrase) -> Boolean) =
+                       filter(predicate).map(Phrase::phrase).map(String::toLowerCase).flatMap { text.findAll(it) }
+
        private fun score(text: String, phrases: Iterable<Phrase>): Double {
                val requiredPhrases = phrases.count { it.required }
-               val requiredHits = phrases.filter(Phrase::required)
-                               .map(Phrase::phrase)
-                               .flatMap { text.findAll(it) }
+               val requiredHits = phrases.indicesFor(text, Phrase::required)
                                .map { Math.pow(1 - it / text.length.toDouble(), 2.0) }
                                .sum()
-               val optionalHits = phrases.filter(Phrase::optional)
-                               .map(Phrase::phrase)
-                               .flatMap { text.findAll(it) }
+               val optionalHits = phrases.indicesFor(text, Phrase::optional)
                                .map { Math.pow(1 - it / text.length.toDouble(), 2.0) }
                                .sum()
-               val forbiddenHits = phrases.filter(Phrase::forbidden)
-                               .map(Phrase::phrase)
-                               .map { text.findAll(it).size }
-                               .sum()
+               val forbiddenHits = phrases.indicesFor(text, Phrase::forbidden)
+                               .count()
                return requiredHits * 3 + optionalHits + (requiredHits - requiredPhrases) * 5 - (forbiddenHits * 2)
        }
 
@@ -122,7 +123,6 @@ class SearchPage @JvmOverloads constructor(template: Template, webInterface: Web
 
        private fun String.parse() =
                        StringEscaper.parseLine(this)
-                                       .map(String::toLowerCase)
                                        .map {
                                                when {
                                                        it == "+" || it == "-" -> Phrase(it, OPTIONAL)