package search

import java.io.File
import java.lang.IllegalArgumentException

typealias Dataset = List<String>
typealias InvertedIndex = Map<String, List<Int>>

fun toLowercaseWords(s: String) = s.split(" ").map(String::lowercase)

fun ask(prompt: String): String {
    println(prompt)
    return readln()
}

fun scanInputFile(filePath: String): Pair<Dataset, InvertedIndex> {
    val lines = mutableListOf<String>()
    val invertedIndex = mutableMapOf<String, MutableList<Int>>()

    var lineIndex = 0
    val file = File(filePath)
    file.forEachLine {
        lines.add(it)
        for (word in toLowercaseWords(it).filter(String::isNotEmpty)) {
            val positions = invertedIndex.getOrDefault(word, mutableListOf())
            positions.add(lineIndex)
            invertedIndex[word] = positions
        }
        lineIndex += 1
    }

    return lines to invertedIndex
}

fun printPeople(dataset: Dataset) {
    println("=== List of people ===")
    dataset.forEach(::println)
}

fun reportResult(matchedItems: Dataset) {
    if (matchedItems.isNotEmpty()) {
        println("${matchedItems.size} persons found:")
        printPeople(matchedItems)
    } else {
        println("No matching people found.")
    }
}

enum class MatchOption {
    ALL,
    ANY,
    NONE,
}

fun toMatchOption(s: String): MatchOption {
    return MatchOption.valueOf(s.uppercase())
}

class Searcher(private val dataset: Dataset, private val invertedIndex: InvertedIndex) {
    fun search(query: String, matchOption: MatchOption): Dataset {
        return when (matchOption) {
            MatchOption.ALL -> ::searchAll
            MatchOption.ANY -> ::searchAny
            MatchOption.NONE -> ::searchNone
        }(toLowercaseWords(query))
    }

    private fun searchAny(queryWords: List<String>): Dataset {
        return queryWords.flatMap { word ->
            invertedIndex
                .getOrDefault(word, mutableListOf())
                .map { dataset[it] }
        }
    }

    private fun searchAll(queryWords: List<String>): Dataset {
        if (queryWords.isEmpty()) return listOf()

        return queryWords
            .map { word ->
                invertedIndex
                    .getOrDefault(word, mutableListOf())
                    .toSet()
            }
            .reduce { acc, indices -> acc.intersect(indices) }
            .map { dataset[it] }
    }

    private fun searchNone(queryWords: List<String>): Dataset {
        if (queryWords.isEmpty()) return dataset

        val allIndices = (0..dataset.lastIndex)
        val anyIndices = queryWords
            .flatMap { word ->
                invertedIndex
                    .getOrDefault(word, mutableListOf())
            }
            .toSet()

        return allIndices
            .subtract(anyIndices)
            .map { dataset[it] }
    }
}

fun createSearcherAndDataset(dataFilePath: String): Pair<Searcher, Dataset> {
    val (dataset, invertedIndex) = scanInputFile(dataFilePath)
    return Searcher(dataset, invertedIndex) to dataset
}

fun matchOptionToQueryPrompt(matchOption: MatchOption): String {
    return when (matchOption) {
        MatchOption.NONE -> "Enter a name or email to search none matching people."
        MatchOption.ANY -> "Enter a name or email to search any matching people."
        MatchOption.ALL -> "Enter a name or email to search all matching people."
    }
}

fun searchAndReportResult(searcher: Searcher) {
    val matchOption = toMatchOption(ask("Select a matching strategy: ALL, ANY, NONE"))
    val query = ask(matchOptionToQueryPrompt(matchOption))

    val matchedItems = searcher.search(query, matchOption)
    reportResult(matchedItems)
}

data class MenuItem(val name: String, val action: () -> Unit)

class Menu(exitItemNumber: Int, private val items: Map<Int, MenuItem>) {
    private val exitItem = exitItemNumber.toString()

    init {
        require(!items.containsKey(exitItemNumber))
    }

    val prompt = buildString {
        append("=== Menu ===")
        append("\n")
        items
            .entries
            .forEach { command ->
                append("${command.key}. ${command.value.name}")
                append("\n")
            }
        append("$exitItem. Exit")
        append("\n")
    }

    fun run(userChoice: String): Boolean {
        if (userChoice == exitItem) {
            return false
        }

        try {
            val menuIndex = userChoice.toInt()
            require(items.containsKey(menuIndex))

            items[menuIndex]!!.action()
        } catch (e: IllegalArgumentException) {
            println("Incorrect option! Try again.")
        }

        return true
    }
}

fun main(args: Array<String>) {
    require(args.size == 2)
    require(args[0] == "--data")

    val (searcher, dataset) = createSearcherAndDataset(args[1])

    val menu = Menu(
        0,
        mapOf(
            1 to MenuItem("Find a person") { searchAndReportResult(searcher) },
            2 to MenuItem("Print all people") { printPeople(dataset) })
    )

    while (true) {
        val moreToRun = menu.run(ask(menu.prompt))
        if (!moreToRun) break
    }

    println("Bye!")
}

Compiled from "Main.kt"
public final class search.MainKt$WhenMappings {
  public static final int[] $EnumSwitchMapping$0;

  static {};
    Code:
       0: invokestatic  #14                 // Method search/MatchOption.values:()[Lsearch/MatchOption;
       3: arraylength
       4: newarray       int
       6: astore_0
       7: nop
       8: aload_0
       9: getstatic     #18                 // Field search/MatchOption.NONE:Lsearch/MatchOption;
      12: invokevirtual #22                 // Method search/MatchOption.ordinal:()I
      15: iconst_1
      16: iastore
      17: goto          21
      20: astore_1
      21: nop
      22: aload_0
      23: getstatic     #25                 // Field search/MatchOption.ANY:Lsearch/MatchOption;
      26: invokevirtual #22                 // Method search/MatchOption.ordinal:()I
      29: iconst_2
      30: iastore
      31: goto          35
      34: astore_1
      35: nop
      36: aload_0
      37: getstatic     #28                 // Field search/MatchOption.ALL:Lsearch/MatchOption;
      40: invokevirtual #22                 // Method search/MatchOption.ordinal:()I
      43: iconst_3
      44: iastore
      45: goto          49
      48: astore_1
      49: aload_0
      50: putstatic     #32                 // Field $EnumSwitchMapping$0:[I
      53: return
    Exception table:
       from    to  target type
           7    17    20   Class java/lang/NoSuchFieldError
          21    31    34   Class java/lang/NoSuchFieldError
          35    45    48   Class java/lang/NoSuchFieldError
}

Compiled from "Main.kt"
public final class search.MainKt {
  public static final java.util.List<java.lang.String> toLowercaseWords(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #10                 // String s
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/CharSequence
      10: iconst_1
      11: anewarray     #20                 // class java/lang/String
      14: astore_1
      15: aload_1
      16: iconst_0
      17: ldc           #22                 // String
      19: aastore
      20: aload_1
      21: iconst_0
      22: iconst_0
      23: bipush        6
      25: aconst_null
      26: invokestatic  #28                 // Method kotlin/text/StringsKt.split$default:(Ljava/lang/CharSequence;[Ljava/lang/String;ZIILjava/lang/Object;)Ljava/util/List;
      29: checkcast     #30                 // class java/lang/Iterable
      32: astore_1
      33: iconst_0
      34: istore_2
      35: aload_1
      36: astore_3
      37: new           #32                 // class java/util/ArrayList
      40: dup
      41: aload_1
      42: bipush        10
      44: invokestatic  #38                 // Method kotlin/collections/CollectionsKt.collectionSizeOrDefault:(Ljava/lang/Iterable;I)I
      47: invokespecial #42                 // Method java/util/ArrayList."<init>":(I)V
      50: checkcast     #44                 // class java/util/Collection
      53: astore        4
      55: iconst_0
      56: istore        5
      58: aload_3
      59: invokeinterface #48,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      64: astore        6
      66: aload         6
      68: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      73: ifeq          126
      76: aload         6
      78: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      83: astore        7
      85: aload         4
      87: aload         7
      89: checkcast     #20                 // class java/lang/String
      92: astore        8
      94: astore        10
      96: iconst_0
      97: istore        9
      99: aload         8
     101: getstatic     #64                 // Field java/util/Locale.ROOT:Ljava/util/Locale;
     104: invokevirtual #68                 // Method java/lang/String.toLowerCase:(Ljava/util/Locale;)Ljava/lang/String;
     107: dup
     108: ldc           #70                 // String toLowerCase(...)
     110: invokestatic  #73                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
     113: nop
     114: aload         10
     116: swap
     117: invokeinterface #77,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     122: pop
     123: goto          66
     126: aload         4
     128: checkcast     #79                 // class java/util/List
     131: nop
     132: areturn

  public static final java.lang.String ask(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #96                 // String prompt
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
       9: aload_0
      10: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      13: invokestatic  #114                // Method kotlin/io/ConsoleKt.readln:()Ljava/lang/String;
      16: areturn

  public static final kotlin.Pair<java.util.List<java.lang.String>, java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>> scanInputFile(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #119                // String filePath
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #32                 // class java/util/ArrayList
       9: dup
      10: invokespecial #122                // Method java/util/ArrayList."<init>":()V
      13: checkcast     #79                 // class java/util/List
      16: astore_1
      17: new           #124                // class java/util/LinkedHashMap
      20: dup
      21: invokespecial #125                // Method java/util/LinkedHashMap."<init>":()V
      24: checkcast     #127                // class java/util/Map
      27: astore_2
      28: new           #129                // class kotlin/jvm/internal/Ref$IntRef
      31: dup
      32: invokespecial #130                // Method kotlin/jvm/internal/Ref$IntRef."<init>":()V
      35: astore_3
      36: new           #132                // class java/io/File
      39: dup
      40: aload_0
      41: invokespecial #135                // Method java/io/File."<init>":(Ljava/lang/String;)V
      44: astore        4
      46: aload         4
      48: aconst_null
      49: aload_1
      50: aload_2
      51: aload_3
      52: invokedynamic #155,  0            // InvokeDynamic #0:invoke:(Ljava/util/List;Ljava/util/Map;Lkotlin/jvm/internal/Ref$IntRef;)Lkotlin/jvm/functions/Function1;
      57: iconst_1
      58: aconst_null
      59: invokestatic  #161                // Method kotlin/io/FilesKt.forEachLine$default:(Ljava/io/File;Ljava/nio/charset/Charset;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
      62: aload_1
      63: aload_2
      64: invokestatic  #167                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      67: areturn

  public static final void printPeople(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #180                // String dataset
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: ldc           #182                // String === List of people ===
       8: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      11: swap
      12: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      15: aload_0
      16: checkcast     #30                 // class java/lang/Iterable
      19: astore_1
      20: iconst_0
      21: istore_2
      22: aload_1
      23: invokeinterface #48,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      28: astore_3
      29: aload_3
      30: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      35: ifeq          66
      38: aload_3
      39: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      44: astore        4
      46: aload         4
      48: astore        5
      50: iconst_0
      51: istore        6
      53: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      56: aload         5
      58: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      61: nop
      62: nop
      63: goto          29
      66: nop
      67: return

  public static final void reportResult(java.util.List<java.lang.String>);
    Code:
       0: aload_0
       1: ldc           #189                // String matchedItems
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #44                 // class java/util/Collection
      10: invokeinterface #192,  1          // InterfaceMethod java/util/Collection.isEmpty:()Z
      15: ifne          22
      18: iconst_1
      19: goto          23
      22: iconst_0
      23: ifeq          64
      26: new           #194                // class java/lang/StringBuilder
      29: dup
      30: invokespecial #195                // Method java/lang/StringBuilder."<init>":()V
      33: aload_0
      34: invokeinterface #199,  1          // InterfaceMethod java/util/List.size:()I
      39: invokevirtual #203                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      42: ldc           #205                // String  persons found:
      44: invokevirtual #208                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      47: invokevirtual #211                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      50: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      53: swap
      54: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      57: aload_0
      58: invokestatic  #213                // Method printPeople:(Ljava/util/List;)V
      61: goto          73
      64: ldc           #215                // String No matching people found.
      66: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
      69: swap
      70: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
      73: return

  public static final search.MatchOption toMatchOption(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #10                 // String s
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: getstatic     #64                 // Field java/util/Locale.ROOT:Ljava/util/Locale;
      10: invokevirtual #220                // Method java/lang/String.toUpperCase:(Ljava/util/Locale;)Ljava/lang/String;
      13: dup
      14: ldc           #222                // String toUpperCase(...)
      16: invokestatic  #73                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullExpressionValue:(Ljava/lang/Object;Ljava/lang/String;)V
      19: invokestatic  #227                // Method search/MatchOption.valueOf:(Ljava/lang/String;)Lsearch/MatchOption;
      22: areturn

  public static final kotlin.Pair<search.Searcher, java.util.List<java.lang.String>> createSearcherAndDataset(java.lang.String);
    Code:
       0: aload_0
       1: ldc           #231                // String dataFilePath
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #233                // Method scanInputFile:(Ljava/lang/String;)Lkotlin/Pair;
      10: astore_1
      11: aload_1
      12: invokevirtual #238                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      15: checkcast     #79                 // class java/util/List
      18: astore_2
      19: aload_1
      20: invokevirtual #241                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      23: checkcast     #127                // class java/util/Map
      26: astore_3
      27: new           #243                // class search/Searcher
      30: dup
      31: aload_2
      32: aload_3
      33: invokespecial #246                // Method search/Searcher."<init>":(Ljava/util/List;Ljava/util/Map;)V
      36: aload_2
      37: invokestatic  #167                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
      40: areturn

  public static final java.lang.String matchOptionToQueryPrompt(search.MatchOption);
    Code:
       0: aload_0
       1: ldc           #250                // String matchOption
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: getstatic     #256                // Field search/MainKt$WhenMappings.$EnumSwitchMapping$0:[I
      10: swap
      11: invokevirtual #259                // Method search/MatchOption.ordinal:()I
      14: iaload
      15: tableswitch   { // 1 to 3
                     1: 40
                     2: 46
                     3: 52
               default: 58
          }
      40: ldc_w         #261                // String Enter a name or email to search none matching people.
      43: goto          66
      46: ldc_w         #263                // String Enter a name or email to search any matching people.
      49: goto          66
      52: ldc_w         #265                // String Enter a name or email to search all matching people.
      55: goto          66
      58: new           #267                // class kotlin/NoWhenBranchMatchedException
      61: dup
      62: invokespecial #268                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
      65: athrow
      66: areturn

  public static final void searchAndReportResult(search.Searcher);
    Code:
       0: aload_0
       1: ldc_w         #273                // String searcher
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: ldc_w         #275                // String Select a matching strategy: ALL, ANY, NONE
      10: invokestatic  #277                // Method ask:(Ljava/lang/String;)Ljava/lang/String;
      13: invokestatic  #279                // Method toMatchOption:(Ljava/lang/String;)Lsearch/MatchOption;
      16: astore_1
      17: aload_1
      18: invokestatic  #281                // Method matchOptionToQueryPrompt:(Lsearch/MatchOption;)Ljava/lang/String;
      21: invokestatic  #277                // Method ask:(Ljava/lang/String;)Ljava/lang/String;
      24: astore_2
      25: aload_0
      26: aload_2
      27: aload_1
      28: invokevirtual #285                // Method search/Searcher.search:(Ljava/lang/String;Lsearch/MatchOption;)Ljava/util/List;
      31: astore_3
      32: aload_3
      33: invokestatic  #287                // Method reportResult:(Ljava/util/List;)V
      36: return

  public static final void main(java.lang.String[]);
    Code:
       0: aload_0
       1: ldc_w         #293                // String args
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: arraylength
       9: iconst_2
      10: if_icmpne     17
      13: iconst_1
      14: goto          18
      17: iconst_0
      18: ifne          37
      21: ldc_w         #295                // String Failed requirement.
      24: astore_2
      25: new           #297                // class java/lang/IllegalArgumentException
      28: dup
      29: aload_2
      30: invokevirtual #298                // Method java/lang/Object.toString:()Ljava/lang/String;
      33: invokespecial #299                // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      36: athrow
      37: aload_0
      38: iconst_0
      39: aaload
      40: ldc_w         #301                // String --data
      43: invokestatic  #305                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      46: ifne          65
      49: ldc_w         #295                // String Failed requirement.
      52: astore_2
      53: new           #297                // class java/lang/IllegalArgumentException
      56: dup
      57: aload_2
      58: invokevirtual #298                // Method java/lang/Object.toString:()Ljava/lang/String;
      61: invokespecial #299                // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      64: athrow
      65: aload_0
      66: iconst_1
      67: aaload
      68: invokestatic  #307                // Method createSearcherAndDataset:(Ljava/lang/String;)Lkotlin/Pair;
      71: astore_1
      72: aload_1
      73: invokevirtual #238                // Method kotlin/Pair.component1:()Ljava/lang/Object;
      76: checkcast     #243                // class search/Searcher
      79: astore_2
      80: aload_1
      81: invokevirtual #241                // Method kotlin/Pair.component2:()Ljava/lang/Object;
      84: checkcast     #79                 // class java/util/List
      87: astore_3
      88: new           #309                // class search/Menu
      91: dup
      92: iconst_0
      93: iconst_2
      94: anewarray     #235                // class kotlin/Pair
      97: astore        5
      99: aload         5
     101: iconst_0
     102: iconst_1
     103: invokestatic  #314                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     106: new           #316                // class search/MenuItem
     109: dup
     110: ldc_w         #318                // String Find a person
     113: aload_2
     114: invokedynamic #329,  0            // InvokeDynamic #1:invoke:(Lsearch/Searcher;)Lkotlin/jvm/functions/Function0;
     119: invokespecial #332                // Method search/MenuItem."<init>":(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
     122: invokestatic  #167                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     125: aastore
     126: aload         5
     128: iconst_1
     129: iconst_2
     130: invokestatic  #314                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     133: new           #316                // class search/MenuItem
     136: dup
     137: ldc_w         #334                // String Print all people
     140: aload_3
     141: invokedynamic #342,  0            // InvokeDynamic #2:invoke:(Ljava/util/List;)Lkotlin/jvm/functions/Function0;
     146: invokespecial #332                // Method search/MenuItem."<init>":(Ljava/lang/String;Lkotlin/jvm/functions/Function0;)V
     149: invokestatic  #167                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     152: aastore
     153: aload         5
     155: invokestatic  #348                // Method kotlin/collections/MapsKt.mapOf:([Lkotlin/Pair;)Ljava/util/Map;
     158: invokespecial #351                // Method search/Menu."<init>":(ILjava/util/Map;)V
     161: astore        4
     163: nop
     164: aload         4
     166: aload         4
     168: invokevirtual #354                // Method search/Menu.getPrompt:()Ljava/lang/String;
     171: invokestatic  #277                // Method ask:(Ljava/lang/String;)Ljava/lang/String;
     174: invokevirtual #358                // Method search/Menu.run:(Ljava/lang/String;)Z
     177: istore        5
     179: iload         5
     181: ifne          163
     184: goto          187
     187: ldc_w         #360                // String Bye!
     190: getstatic     #102                // Field java/lang/System.out:Ljava/io/PrintStream;
     193: swap
     194: invokevirtual #108                // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
     197: return

  private static final kotlin.Unit scanInputFile$lambda$1(java.util.List, java.util.Map, kotlin.jvm.internal.Ref$IntRef, java.lang.String);
    Code:
       0: aload_3
       1: ldc_w         #368                // String it
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: aload_0
       8: aload_3
       9: invokeinterface #369,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
      14: pop
      15: aload_3
      16: invokestatic  #371                // Method toLowercaseWords:(Ljava/lang/String;)Ljava/util/List;
      19: checkcast     #30                 // class java/lang/Iterable
      22: astore        5
      24: iconst_0
      25: istore        6
      27: aload         5
      29: astore        7
      31: new           #32                 // class java/util/ArrayList
      34: dup
      35: invokespecial #122                // Method java/util/ArrayList."<init>":()V
      38: checkcast     #44                 // class java/util/Collection
      41: astore        8
      43: iconst_0
      44: istore        9
      46: aload         7
      48: invokeinterface #48,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      53: astore        10
      55: aload         10
      57: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      62: ifeq          119
      65: aload         10
      67: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      72: astore        11
      74: aload         11
      76: checkcast     #20                 // class java/lang/String
      79: astore        12
      81: iconst_0
      82: istore        13
      84: aload         12
      86: checkcast     #18                 // class java/lang/CharSequence
      89: invokeinterface #374,  1          // InterfaceMethod java/lang/CharSequence.length:()I
      94: ifle          101
      97: iconst_1
      98: goto          102
     101: iconst_0
     102: nop
     103: ifeq          55
     106: aload         8
     108: aload         11
     110: invokeinterface #77,  2           // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     115: pop
     116: goto          55
     119: aload         8
     121: checkcast     #79                 // class java/util/List
     124: nop
     125: invokeinterface #375,  1          // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     130: astore        4
     132: aload         4
     134: invokeinterface #54,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
     139: ifeq          206
     142: aload         4
     144: invokeinterface #58,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     149: checkcast     #20                 // class java/lang/String
     152: astore        5
     154: aload_1
     155: aload         5
     157: new           #32                 // class java/util/ArrayList
     160: dup
     161: invokespecial #122                // Method java/util/ArrayList."<init>":()V
     164: checkcast     #79                 // class java/util/List
     167: invokeinterface #379,  3          // InterfaceMethod java/util/Map.getOrDefault:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     172: checkcast     #79                 // class java/util/List
     175: astore        6
     177: aload         6
     179: aload_2
     180: getfield      #382                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     183: invokestatic  #314                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     186: invokeinterface #369,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     191: pop
     192: aload_1
     193: aload         5
     195: aload         6
     197: invokeinterface #385,  3          // InterfaceMethod java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
     202: pop
     203: goto          132
     206: aload_2
     207: aload_2
     208: getfield      #382                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     211: iconst_1
     212: iadd
     213: putfield      #382                // Field kotlin/jvm/internal/Ref$IntRef.element:I
     216: getstatic     #391                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     219: areturn

  private static final kotlin.Unit main$lambda$3(search.Searcher);
    Code:
       0: aload_0
       1: invokestatic  #404                // Method searchAndReportResult:(Lsearch/Searcher;)V
       4: getstatic     #391                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
       7: areturn

  private static final kotlin.Unit main$lambda$4(java.util.List);
    Code:
       0: aload_0
       1: invokestatic  #213                // Method printPeople:(Ljava/util/List;)V
       4: getstatic     #391                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
       7: areturn
}


package com.kvl.cyclotrack

import kotlin.math.pow

fun List<Double>.average(): Double =
    this.reduce { acc, d -> acc + d } / this.size

fun average(newValue: Double, sampleSize: Int, lastAverage: Double): Double =
    (lastAverage * (sampleSize - 1) + newValue) / sampleSize

fun List<Double>.sampleVariance(): Double {
    val avg = this.average()
    return this.fold(0.0, { acc, d -> acc + (d - avg).pow(2.0) }) / (this.size - 1)
}

fun sampleVariance(
    newValue: Double,
    oldVariance: Double,
    sampleSize: Int,
    oldAverage: Double,
): Double {
    return (oldVariance * (sampleSize - 2) / (sampleSize - 1)) + ((newValue - oldAverage).pow(
        2.0) / sampleSize)
}

fun List<Double>.populationVariance(): Double {
    val avg = this.average()
    return this.fold(0.0, { acc, d -> acc + (d - avg).pow(2.0) }) / this.size
}

fun exponentialSmoothing(alpha: Double, current: Double, last: Double) =
    (alpha * current) + ((1 - alpha) * last)

fun doubleExponentialSmoothing(
    alpha: Double,
    current: Double,
    smoothLast: Double,
    trendLast: Double,
) =
    alpha * current + ((1 - alpha) * (smoothLast + trendLast))

fun doubleExponentialSmoothingTrend(
    beta: Double,
    smooth: Double,
    smoothLast: Double,
    trendLast: Double,
) =
    beta * (smooth - smoothLast) + (1 - beta) * trendLast

fun smooth(alpha: Double, data: Array<Pair<Double, Double>>): List<Pair<Double, Double>> {
    var smoothedFirst = data[0].first
    var smoothedSecond = data[0].second
    return data.map { datum ->
        smoothedFirst = exponentialSmoothing(alpha, datum.first, smoothedFirst)
        smoothedSecond = exponentialSmoothing(alpha, datum.second, smoothedSecond)
        Pair(smoothedFirst, smoothedSecond)
    }
}

fun doubleSmooth(alpha: Double, beta: Double, data: Array<Double>): List<Double> {
    var smoothed: Double = data[0]
    var trend: Double = data[1] - data[0]
    var smoothedLast = smoothed
    return data.map { datum ->
        smoothed = doubleExponentialSmoothing(alpha, datum, smoothedLast, trend)
        trend = doubleExponentialSmoothingTrend(beta, smoothed, smoothedLast, trend)
        smoothedLast = smoothed
        smoothed
    }
}

fun isRangeGreaterThan(left: Pair<Double, Double>, right: Double): Boolean {
    val leftRange = Pair(left.first - left.second, left.first + left.second)
    return leftRange.first > right
}

fun isRangeLessThan(left: Pair<Double, Double>, right: Double): Boolean {
    val leftRange = Pair(left.first - left.second, left.first + left.second)
    return leftRange.second < right
}

fun isRangeGreaterThan(left: Pair<Double, Double>, right: Pair<Double, Double>): Boolean {
    val leftRange = Pair(left.first - left.second, left.first + left.second)
    val rightRange = Pair(right.first - right.second, right.first + right.second)
    return leftRange.first > rightRange.second
}

fun isRangeLessThan(left: Pair<Double, Double>, right: Pair<Double, Double>): Boolean {
    val leftRange = Pair(left.first - left.second, left.first + left.second)
    val rightRange = Pair(right.first - right.second, right.first + right.second)
    return leftRange.second < rightRange.first
}

fun leastSquaresFitSlope(data: List<Pair<Double, Double>>): Double {
    //https://stats.libretexts.org/Bookshelves/Introductory_Statistics/Book%3A_Introductory_Statistics_(Shafer_and_Zhang)/10%3A_Correlation_and_Regression/10.04%3A_The_Least_Squares_Regression_Line

    var sumx = 0.0
    var sumy = 0.0
    var sumxsq = 0.0
    var sumxy = 0.0

    data.forEach {
        sumx += it.first
        sumy += it.second
        sumxsq += it.first * it.first
        sumxy += it.first * it.second
    }

    val ssxy = sumxy - ((1.0 / data.size) * sumx * sumy)
    val ssxx = sumxsq - ((1.0 / data.size) * sumx * sumx)

    return ssxy / ssxx
}

fun accumulateAscentDescent(elevationData: List<Pair<Double, Double>>): Pair<Double, Double> {
    var totalAscent = 0.0
    var totalDescent = 0.0
    var altitudeCursor = elevationData[0]

    elevationData.forEach { sample ->
        if (isRangeGreaterThan(sample, altitudeCursor)) {
            totalAscent += sample.first - altitudeCursor.first
            altitudeCursor = sample
        }
        if (isRangeLessThan(sample, altitudeCursor)) {
            totalDescent += sample.first - altitudeCursor.first
            altitudeCursor = sample
        }
    }

    return Pair(totalAscent, totalDescent)
}

Compiled from "Statistics.kt"
public final class com.kvl.cyclotrack.StatisticsKt {
  public static final double average(java.util.List<java.lang.Double>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: checkcast     #18                 // class java/lang/Iterable
      10: astore_1
      11: iconst_0
      12: istore_2
      13: aload_1
      14: invokeinterface #22,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      19: astore_3
      20: aload_3
      21: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      26: ifne          39
      29: new           #30                 // class java/lang/UnsupportedOperationException
      32: dup
      33: ldc           #32                 // String Empty collection can\'t be reduced.
      35: invokespecial #36                 // Method java/lang/UnsupportedOperationException."<init>":(Ljava/lang/String;)V
      38: athrow
      39: aload_3
      40: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      45: astore        4
      47: aload_3
      48: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      53: ifeq          96
      56: aload         4
      58: aload_3
      59: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      64: checkcast     #42                 // class java/lang/Number
      67: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      70: dstore        5
      72: checkcast     #42                 // class java/lang/Number
      75: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      78: dstore        7
      80: iconst_0
      81: istore        9
      83: dload         7
      85: dload         5
      87: dadd
      88: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      91: astore        4
      93: goto          47
      96: aload         4
      98: checkcast     #42                 // class java/lang/Number
     101: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     104: aload_0
     105: invokeinterface #58,  1           // InterfaceMethod java/util/List.size:()I
     110: i2d
     111: ddiv
     112: dreturn

  public static final double average(double, int, double);
    Code:
       0: dload_3
       1: iload_2
       2: iconst_1
       3: isub
       4: i2d
       5: dmul
       6: dload_0
       7: dadd
       8: iload_2
       9: i2d
      10: ddiv
      11: dreturn

  public static final double sampleVariance(java.util.List<java.lang.Double>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #79                 // Method average:(Ljava/util/List;)D
      10: dstore_1
      11: aload_0
      12: checkcast     #18                 // class java/lang/Iterable
      15: astore_3
      16: dconst_0
      17: dstore        4
      19: iconst_0
      20: istore        6
      22: dload         4
      24: dstore        7
      26: aload_3
      27: invokeinterface #22,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      32: astore        9
      34: aload         9
      36: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      41: ifeq          88
      44: aload         9
      46: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      51: astore        10
      53: dload         7
      55: aload         10
      57: checkcast     #42                 // class java/lang/Number
      60: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      63: dstore        11
      65: dstore        13
      67: iconst_0
      68: istore        15
      70: dload         13
      72: dload         11
      74: dload_1
      75: dsub
      76: ldc2_w        #80                 // double 2.0d
      79: invokestatic  #87                 // Method java/lang/Math.pow:(DD)D
      82: dadd
      83: dstore        7
      85: goto          34
      88: dload         7
      90: aload_0
      91: invokeinterface #58,  1           // InterfaceMethod java/util/List.size:()I
      96: iconst_1
      97: isub
      98: i2d
      99: ddiv
     100: dreturn

  public static final double sampleVariance(double, double, int, double);
    Code:
       0: dload_2
       1: iload         4
       3: iconst_2
       4: isub
       5: i2d
       6: dmul
       7: iload         4
       9: iconst_1
      10: isub
      11: i2d
      12: ddiv
      13: dload_0
      14: dload         5
      16: dsub
      17: ldc2_w        #80                 // double 2.0d
      20: invokestatic  #87                 // Method java/lang/Math.pow:(DD)D
      23: iload         4
      25: i2d
      26: ddiv
      27: dadd
      28: dreturn

  public static final double populationVariance(java.util.List<java.lang.Double>);
    Code:
       0: aload_0
       1: ldc           #10                 // String <this>
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: invokestatic  #79                 // Method average:(Ljava/util/List;)D
      10: dstore_1
      11: aload_0
      12: checkcast     #18                 // class java/lang/Iterable
      15: astore_3
      16: dconst_0
      17: dstore        4
      19: iconst_0
      20: istore        6
      22: dload         4
      24: dstore        7
      26: aload_3
      27: invokeinterface #22,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      32: astore        9
      34: aload         9
      36: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      41: ifeq          88
      44: aload         9
      46: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      51: astore        10
      53: dload         7
      55: aload         10
      57: checkcast     #42                 // class java/lang/Number
      60: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      63: dstore        11
      65: dstore        13
      67: iconst_0
      68: istore        15
      70: dload         13
      72: dload         11
      74: dload_1
      75: dsub
      76: ldc2_w        #80                 // double 2.0d
      79: invokestatic  #87                 // Method java/lang/Math.pow:(DD)D
      82: dadd
      83: dstore        7
      85: goto          34
      88: dload         7
      90: aload_0
      91: invokeinterface #58,  1           // InterfaceMethod java/util/List.size:()I
      96: i2d
      97: ddiv
      98: dreturn

  public static final double exponentialSmoothing(double, double, double);
    Code:
       0: dload_0
       1: dload_2
       2: dmul
       3: iconst_1
       4: i2d
       5: dload_0
       6: dsub
       7: dload         4
       9: dmul
      10: dadd
      11: dreturn

  public static final double doubleExponentialSmoothing(double, double, double, double);
    Code:
       0: dload_0
       1: dload_2
       2: dmul
       3: iconst_1
       4: i2d
       5: dload_0
       6: dsub
       7: dload         4
       9: dload         6
      11: dadd
      12: dmul
      13: dadd
      14: dreturn

  public static final double doubleExponentialSmoothingTrend(double, double, double, double);
    Code:
       0: dload_0
       1: dload_2
       2: dload         4
       4: dsub
       5: dmul
       6: iconst_1
       7: i2d
       8: dload_0
       9: dsub
      10: dload         6
      12: dmul
      13: dadd
      14: dreturn

  public static final java.util.List<kotlin.Pair<java.lang.Double, java.lang.Double>> smooth(double, kotlin.Pair<java.lang.Double, java.lang.Double>[]);
    Code:
       0: aload_2
       1: ldc           #116                // String data
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: dconst_0
       7: dstore        14
       9: aload_2
      10: iconst_0
      11: aaload
      12: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      15: checkcast     #42                 // class java/lang/Number
      18: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      21: dstore        14
      23: dconst_0
      24: dstore        16
      26: aload_2
      27: iconst_0
      28: aaload
      29: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      32: checkcast     #42                 // class java/lang/Number
      35: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      38: dstore        16
      40: aload_2
      41: astore_3
      42: iconst_0
      43: istore        4
      45: aload_3
      46: astore        5
      48: new           #126                // class java/util/ArrayList
      51: dup
      52: aload_3
      53: arraylength
      54: invokespecial #129                // Method java/util/ArrayList."<init>":(I)V
      57: checkcast     #131                // class java/util/Collection
      60: astore        6
      62: iconst_0
      63: istore        7
      65: iconst_0
      66: istore        8
      68: aload         5
      70: arraylength
      71: istore        9
      73: iload         8
      75: iload         9
      77: if_icmpge     168
      80: aload         5
      82: iload         8
      84: aaload
      85: astore        10
      87: aload         6
      89: aload         10
      91: astore        11
      93: astore        13
      95: iconst_0
      96: istore        12
      98: dload_0
      99: aload         11
     101: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     104: checkcast     #42                 // class java/lang/Number
     107: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     110: dload         14
     112: invokestatic  #133                // Method exponentialSmoothing:(DDD)D
     115: dstore        14
     117: dload_0
     118: aload         11
     120: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     123: checkcast     #42                 // class java/lang/Number
     126: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     129: dload         16
     131: invokestatic  #133                // Method exponentialSmoothing:(DDD)D
     134: dstore        16
     136: new           #118                // class kotlin/Pair
     139: dup
     140: dload         14
     142: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     145: dload         16
     147: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     150: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     153: aload         13
     155: swap
     156: invokeinterface #140,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     161: pop
     162: iinc          8, 1
     165: goto          73
     168: aload         6
     170: checkcast     #54                 // class java/util/List
     173: nop
     174: areturn

  public static final java.util.List<java.lang.Double> doubleSmooth(double, double, java.lang.Double[]);
    Code:
       0: aload         4
       2: ldc           #116                // String data
       4: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       7: dconst_0
       8: dstore        17
      10: aload         4
      12: iconst_0
      13: aaload
      14: invokevirtual #159                // Method java/lang/Double.doubleValue:()D
      17: dstore        17
      19: dconst_0
      20: dstore        19
      22: aload         4
      24: iconst_1
      25: aaload
      26: invokevirtual #159                // Method java/lang/Double.doubleValue:()D
      29: aload         4
      31: iconst_0
      32: aaload
      33: invokevirtual #159                // Method java/lang/Double.doubleValue:()D
      36: dsub
      37: dstore        19
      39: dconst_0
      40: dstore        21
      42: dload         17
      44: dstore        21
      46: aload         4
      48: astore        5
      50: iconst_0
      51: istore        6
      53: aload         5
      55: astore        7
      57: new           #126                // class java/util/ArrayList
      60: dup
      61: aload         5
      63: arraylength
      64: invokespecial #129                // Method java/util/ArrayList."<init>":(I)V
      67: checkcast     #131                // class java/util/Collection
      70: astore        8
      72: iconst_0
      73: istore        9
      75: iconst_0
      76: istore        10
      78: aload         7
      80: arraylength
      81: istore        11
      83: iload         10
      85: iload         11
      87: if_icmpge     162
      90: aload         7
      92: iload         10
      94: aaload
      95: astore        12
      97: aload         8
      99: aload         12
     101: checkcast     #42                 // class java/lang/Number
     104: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     107: dstore        13
     109: astore        16
     111: iconst_0
     112: istore        15
     114: dload_0
     115: dload         13
     117: dload         21
     119: dload         19
     121: invokestatic  #161                // Method doubleExponentialSmoothing:(DDDD)D
     124: dstore        17
     126: dload_2
     127: dload         17
     129: dload         21
     131: dload         19
     133: invokestatic  #163                // Method doubleExponentialSmoothingTrend:(DDDD)D
     136: dstore        19
     138: dload         17
     140: dstore        21
     142: dload         17
     144: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     147: aload         16
     149: swap
     150: invokeinterface #140,  2          // InterfaceMethod java/util/Collection.add:(Ljava/lang/Object;)Z
     155: pop
     156: iinc          10, 1
     159: goto          83
     162: aload         8
     164: checkcast     #54                 // class java/util/List
     167: nop
     168: areturn

  public static final boolean isRangeGreaterThan(kotlin.Pair<java.lang.Double, java.lang.Double>, double);
    Code:
       0: aload_0
       1: ldc           #174                // String left
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #118                // class kotlin/Pair
       9: dup
      10: aload_0
      11: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      14: checkcast     #42                 // class java/lang/Number
      17: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      20: aload_0
      21: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      24: checkcast     #42                 // class java/lang/Number
      27: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      30: dsub
      31: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      34: aload_0
      35: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      38: checkcast     #42                 // class java/lang/Number
      41: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      44: aload_0
      45: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      48: checkcast     #42                 // class java/lang/Number
      51: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      54: dadd
      55: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      58: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      61: astore_3
      62: aload_3
      63: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      66: checkcast     #42                 // class java/lang/Number
      69: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      72: dload_1
      73: dcmpl
      74: ifle          81
      77: iconst_1
      78: goto          82
      81: iconst_0
      82: ireturn

  public static final boolean isRangeLessThan(kotlin.Pair<java.lang.Double, java.lang.Double>, double);
    Code:
       0: aload_0
       1: ldc           #174                // String left
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #118                // class kotlin/Pair
       9: dup
      10: aload_0
      11: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      14: checkcast     #42                 // class java/lang/Number
      17: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      20: aload_0
      21: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      24: checkcast     #42                 // class java/lang/Number
      27: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      30: dsub
      31: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      34: aload_0
      35: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      38: checkcast     #42                 // class java/lang/Number
      41: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      44: aload_0
      45: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      48: checkcast     #42                 // class java/lang/Number
      51: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      54: dadd
      55: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      58: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      61: astore_3
      62: aload_3
      63: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      66: checkcast     #42                 // class java/lang/Number
      69: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      72: dload_1
      73: dcmpg
      74: ifge          81
      77: iconst_1
      78: goto          82
      81: iconst_0
      82: ireturn

  public static final boolean isRangeGreaterThan(kotlin.Pair<java.lang.Double, java.lang.Double>, kotlin.Pair<java.lang.Double, java.lang.Double>);
    Code:
       0: aload_0
       1: ldc           #174                // String left
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #180                // String right
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: new           #118                // class kotlin/Pair
      15: dup
      16: aload_0
      17: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      20: checkcast     #42                 // class java/lang/Number
      23: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      26: aload_0
      27: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      30: checkcast     #42                 // class java/lang/Number
      33: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      36: dsub
      37: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      40: aload_0
      41: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      44: checkcast     #42                 // class java/lang/Number
      47: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      50: aload_0
      51: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      54: checkcast     #42                 // class java/lang/Number
      57: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      60: dadd
      61: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      64: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      67: astore_2
      68: new           #118                // class kotlin/Pair
      71: dup
      72: aload_1
      73: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      76: checkcast     #42                 // class java/lang/Number
      79: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      82: aload_1
      83: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      86: checkcast     #42                 // class java/lang/Number
      89: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      92: dsub
      93: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      96: aload_1
      97: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     100: checkcast     #42                 // class java/lang/Number
     103: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     106: aload_1
     107: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     110: checkcast     #42                 // class java/lang/Number
     113: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     116: dadd
     117: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     120: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     123: astore_3
     124: aload_2
     125: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     128: checkcast     #42                 // class java/lang/Number
     131: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     134: aload_3
     135: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     138: checkcast     #42                 // class java/lang/Number
     141: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     144: dcmpl
     145: ifle          152
     148: iconst_1
     149: goto          153
     152: iconst_0
     153: ireturn

  public static final boolean isRangeLessThan(kotlin.Pair<java.lang.Double, java.lang.Double>, kotlin.Pair<java.lang.Double, java.lang.Double>);
    Code:
       0: aload_0
       1: ldc           #174                // String left
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_1
       7: ldc           #180                // String right
       9: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: new           #118                // class kotlin/Pair
      15: dup
      16: aload_0
      17: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      20: checkcast     #42                 // class java/lang/Number
      23: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      26: aload_0
      27: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      30: checkcast     #42                 // class java/lang/Number
      33: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      36: dsub
      37: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      40: aload_0
      41: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      44: checkcast     #42                 // class java/lang/Number
      47: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      50: aload_0
      51: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      54: checkcast     #42                 // class java/lang/Number
      57: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      60: dadd
      61: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      64: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
      67: astore_2
      68: new           #118                // class kotlin/Pair
      71: dup
      72: aload_1
      73: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      76: checkcast     #42                 // class java/lang/Number
      79: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      82: aload_1
      83: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      86: checkcast     #42                 // class java/lang/Number
      89: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      92: dsub
      93: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
      96: aload_1
      97: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     100: checkcast     #42                 // class java/lang/Number
     103: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     106: aload_1
     107: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     110: checkcast     #42                 // class java/lang/Number
     113: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     116: dadd
     117: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     120: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     123: astore_3
     124: aload_2
     125: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     128: checkcast     #42                 // class java/lang/Number
     131: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     134: aload_3
     135: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     138: checkcast     #42                 // class java/lang/Number
     141: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     144: dcmpg
     145: ifge          152
     148: iconst_1
     149: goto          153
     152: iconst_0
     153: ireturn

  public static final double leastSquaresFitSlope(java.util.List<kotlin.Pair<java.lang.Double, java.lang.Double>>);
    Code:
       0: aload_0
       1: ldc           #116                // String data
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: dconst_0
       7: dstore        7
       9: dconst_0
      10: dstore        9
      12: dconst_0
      13: dstore        11
      15: dconst_0
      16: dstore        13
      18: aload_0
      19: checkcast     #18                 // class java/lang/Iterable
      22: astore_1
      23: iconst_0
      24: istore_2
      25: aload_1
      26: invokeinterface #22,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      31: astore_3
      32: aload_3
      33: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      38: ifeq          152
      41: aload_3
      42: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      47: astore        4
      49: aload         4
      51: checkcast     #118                // class kotlin/Pair
      54: astore        5
      56: iconst_0
      57: istore        6
      59: dload         7
      61: aload         5
      63: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      66: checkcast     #42                 // class java/lang/Number
      69: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      72: dadd
      73: dstore        7
      75: dload         9
      77: aload         5
      79: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
      82: checkcast     #42                 // class java/lang/Number
      85: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      88: dadd
      89: dstore        9
      91: dload         11
      93: aload         5
      95: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      98: checkcast     #42                 // class java/lang/Number
     101: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     104: aload         5
     106: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     109: checkcast     #42                 // class java/lang/Number
     112: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     115: dmul
     116: dadd
     117: dstore        11
     119: dload         13
     121: aload         5
     123: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     126: checkcast     #42                 // class java/lang/Number
     129: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     132: aload         5
     134: invokevirtual #124                // Method kotlin/Pair.getSecond:()Ljava/lang/Object;
     137: checkcast     #42                 // class java/lang/Number
     140: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     143: dmul
     144: dadd
     145: dstore        13
     147: nop
     148: nop
     149: goto          32
     152: nop
     153: dload         13
     155: dconst_1
     156: aload_0
     157: invokeinterface #58,  1           // InterfaceMethod java/util/List.size:()I
     162: i2d
     163: ddiv
     164: dload         7
     166: dmul
     167: dload         9
     169: dmul
     170: dsub
     171: dstore_1
     172: dload         11
     174: dconst_1
     175: aload_0
     176: invokeinterface #58,  1           // InterfaceMethod java/util/List.size:()I
     181: i2d
     182: ddiv
     183: dload         7
     185: dmul
     186: dload         7
     188: dmul
     189: dsub
     190: dstore_3
     191: dload_1
     192: dload_3
     193: ddiv
     194: dreturn

  public static final kotlin.Pair<java.lang.Double, java.lang.Double> accumulateAscentDescent(java.util.List<kotlin.Pair<java.lang.Double, java.lang.Double>>);
    Code:
       0: aload_0
       1: ldc           #198                // String elevationData
       3: invokestatic  #16                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: dconst_0
       7: dstore        8
       9: dconst_0
      10: dstore        10
      12: aconst_null
      13: astore_1
      14: aload_0
      15: iconst_0
      16: invokeinterface #202,  2          // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
      21: astore_1
      22: aload_0
      23: checkcast     #18                 // class java/lang/Iterable
      26: astore_2
      27: iconst_0
      28: istore_3
      29: aload_2
      30: invokeinterface #22,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      35: astore        4
      37: aload         4
      39: invokeinterface #28,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      44: ifeq          161
      47: aload         4
      49: invokeinterface #40,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
      54: astore        5
      56: aload         5
      58: checkcast     #118                // class kotlin/Pair
      61: astore        6
      63: iconst_0
      64: istore        7
      66: aload         6
      68: aload_1
      69: checkcast     #118                // class kotlin/Pair
      72: invokestatic  #204                // Method isRangeGreaterThan:(Lkotlin/Pair;Lkotlin/Pair;)Z
      75: ifeq          111
      78: dload         8
      80: aload         6
      82: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      85: checkcast     #42                 // class java/lang/Number
      88: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
      91: aload_1
      92: checkcast     #118                // class kotlin/Pair
      95: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
      98: checkcast     #42                 // class java/lang/Number
     101: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     104: dsub
     105: dadd
     106: dstore        8
     108: aload         6
     110: astore_1
     111: aload         6
     113: aload_1
     114: checkcast     #118                // class kotlin/Pair
     117: invokestatic  #206                // Method isRangeLessThan:(Lkotlin/Pair;Lkotlin/Pair;)Z
     120: ifeq          156
     123: dload         10
     125: aload         6
     127: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     130: checkcast     #42                 // class java/lang/Number
     133: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     136: aload_1
     137: checkcast     #118                // class kotlin/Pair
     140: invokevirtual #121                // Method kotlin/Pair.getFirst:()Ljava/lang/Object;
     143: checkcast     #42                 // class java/lang/Number
     146: invokevirtual #46                 // Method java/lang/Number.doubleValue:()D
     149: dsub
     150: dadd
     151: dstore        10
     153: aload         6
     155: astore_1
     156: nop
     157: nop
     158: goto          37
     161: nop
     162: new           #118                // class kotlin/Pair
     165: dup
     166: dload         8
     168: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     171: dload         10
     173: invokestatic  #52                 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
     176: invokespecial #136                // Method kotlin/Pair."<init>":(Ljava/lang/Object;Ljava/lang/Object;)V
     179: areturn
}