Skip to content

Commit

Permalink
Merge branch 'main' into weblate-trail-sense-trail-sense-android
Browse files Browse the repository at this point in the history
  • Loading branch information
kylecorry31 authored Feb 17, 2025
2 parents f89f8cc + b129dca commit b913ed4
Show file tree
Hide file tree
Showing 15 changed files with 1,109 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
package com.kylecorry.trail_sense.tools.survival_guide

import com.kylecorry.trail_sense.R
import com.kylecorry.trail_sense.test_utils.AutomationLibrary.click
import com.kylecorry.trail_sense.test_utils.AutomationLibrary.clickOk
import com.kylecorry.trail_sense.test_utils.AutomationLibrary.hasText
import com.kylecorry.trail_sense.test_utils.AutomationLibrary.isVisible
import com.kylecorry.trail_sense.test_utils.AutomationLibrary.scrollToEnd
import com.kylecorry.trail_sense.test_utils.TestUtils.back
import com.kylecorry.trail_sense.test_utils.TestUtils.context
import com.kylecorry.trail_sense.test_utils.ToolTestBase
import com.kylecorry.trail_sense.tools.survival_guide.domain.Chapters
import com.kylecorry.trail_sense.tools.tools.infrastructure.Tools
import org.junit.Test

class ToolSurvivalGuideTest : ToolTestBase(Tools.SURVIVAL_GUIDE) {
@Test
fun verifyBasicFunctionality() {
// Accept the disclaimer
clickOk()

isVisible(R.id.survival_guide_list_title)

// Verify it shows each chapter
val chapters = Chapters.getChapters(context)
chapters.forEachIndexed { index, chapter ->
if (index > 6) {
scrollToEnd(R.id.survival_guide_chapters_list)
}

click(chapter.title)

// Wait for the chapter to load
hasText(R.id.guide_name, chapter.title)
hasText(R.id.guide_scroll) { it.isNotEmpty() }
click("Be prepared")

back()
}
}
}
// TODO: Re-enable this test
//package com.kylecorry.trail_sense.tools.survival_guide
//
//import com.kylecorry.trail_sense.R
//import com.kylecorry.trail_sense.test_utils.AutomationLibrary.click
//import com.kylecorry.trail_sense.test_utils.AutomationLibrary.clickOk
//import com.kylecorry.trail_sense.test_utils.AutomationLibrary.hasText
//import com.kylecorry.trail_sense.test_utils.AutomationLibrary.isVisible
//import com.kylecorry.trail_sense.test_utils.AutomationLibrary.scrollToEnd
//import com.kylecorry.trail_sense.test_utils.TestUtils.back
//import com.kylecorry.trail_sense.test_utils.TestUtils.context
//import com.kylecorry.trail_sense.test_utils.ToolTestBase
//import com.kylecorry.trail_sense.tools.survival_guide.domain.Chapters
//import com.kylecorry.trail_sense.tools.tools.infrastructure.Tools
//import org.junit.Test
//
//class ToolSurvivalGuideTest : ToolTestBase(Tools.SURVIVAL_GUIDE) {
// @Test
// fun verifyBasicFunctionality() {
// // Accept the disclaimer
// clickOk()
//
// isVisible(R.id.survival_guide_list_title)
//
// // Verify it shows each chapter
// val chapters = Chapters.getChapters(context)
// chapters.forEachIndexed { index, chapter ->
// if (index > 6) {
// scrollToEnd(R.id.survival_guide_chapters_list)
// }
//
// click(chapter.title)
//
// // Wait for the chapter to load
// hasText(R.id.guide_name, chapter.title)
// hasText(R.id.guide_scroll) { it.isNotEmpty() }
// click("Be prepared")
//
// back()
// }
// }
//}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.kylecorry.trail_sense.shared.text

class ContractionSplitter(private val additionalContractions: Map<String, List<String>> = emptyMap()) {

fun split(words: List<String>): List<String> {
return words.flatMap { split(it) }
}

fun split(word: String): List<String> {
val contractions = mapOf(
"n't" to "not",
"'ve" to "have",
"'ll" to "will",
"'re" to "are",
"'d" to "would",
)

// Contractions that aren't just the base word + a suffix
val specialContractions = mapOf(
"it's" to listOf("it", "is"),
"he's" to listOf("he", "is"),
"she's" to listOf("she", "is"),
"that's" to listOf("that", "is"),
"there's" to listOf("there", "is"),
"what's" to listOf("what", "is"),
"where's" to listOf("where", "is"),
"who's" to listOf("who", "is"),
"how's" to listOf("how", "is"),
"let's" to listOf("let", "us"),
"cannot" to listOf("can", "not"),
"won't" to listOf("will", "not"),
"shan't" to listOf("shall", "not"),
"can't" to listOf("can", "not"),
) + additionalContractions

if (word in specialContractions) {
return specialContractions[word] ?: listOf()
}

for ((contraction, replacement) in contractions) {
if (word.endsWith(contraction)) {
return listOf(word.substring(0, word.length - contraction.length), replacement)
}
}

return listOf(word)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.kylecorry.trail_sense.shared.text

class KeywordTokenizer(
preservedWords: Set<String> = emptySet(),
additionalContractions: Map<String, List<String>> = emptyMap(),
additionalStopWords: Set<String> = emptySet(),
additionalStemWords: Map<String, String> = emptyMap()
) : Tokenizer {

private val wordTokenizer = SimpleWordTokenizer(preservedWords)
private val contractionSplitter = ContractionSplitter(additionalContractions)
private val stopWordRemover = StopWordRemover(additionalStopWords)
private val stemmer = PorterStemmer(additionalStemWords)

override fun tokenize(text: String): List<String> {
return stemmer.stem(
stopWordRemover.clean(
contractionSplitter.split(
wordTokenizer.tokenize(text).map { it.lowercase() }
)
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.kylecorry.trail_sense.shared.text

class LevenshteinDistance {

fun editDistance(s1: String, s2: String): Int {
if (s1 == s2) {
return 0
}

if (s1.length < s2.length) {
return editDistance(s2, s1)
}

var previousRow = IntArray(s2.length + 1) { it }
for (i in s1.indices) {
val currentRow = IntArray(s2.length + 1) { i + 1 }
for (j in s2.indices) {
val insertions = previousRow[j + 1] + 1
val deletions = currentRow[j] + 1
val substitutions = previousRow[j] + if (s1[i] != s2[j]) 1 else 0
currentRow[j + 1] = minOf(insertions, deletions, substitutions)
}
previousRow = currentRow
}

return previousRow.last()
}

fun percentSimilarity(s1: String, s2: String): Float {
return 1 - editDistance(s1, s2).toFloat() / maxOf(s1.length, s2.length)
}

}
Loading

0 comments on commit b913ed4

Please sign in to comment.