mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-11-25 02:14:32 +01:00
IOS Implementation (WIP), use FuzzyWuzzy as a Lib and many more changes
This commit is contained in:
parent
2b0a33d8a1
commit
1b18b9cf09
@ -91,14 +91,14 @@ object JetBrains {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
object Decompose {
|
object Decompose {
|
||||||
private const val VERSION = "0.2.1"
|
private const val VERSION = "0.2.3"
|
||||||
const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
|
const val decompose = "com.arkivanov.decompose:decompose:$VERSION"
|
||||||
const val decomposeIosX64 = "com.arkivanov.decompose:decompose-iosx64:$VERSION"
|
const val decomposeIosX64 = "com.arkivanov.decompose:decompose-iosx64:$VERSION"
|
||||||
const val decomposeIosArm64 = "com.arkivanov.decompose:decompose-iosarm64:$VERSION"
|
const val decomposeIosArm64 = "com.arkivanov.decompose:decompose-iosarm64:$VERSION"
|
||||||
const val extensionsCompose = "com.arkivanov.decompose:extensions-compose-jetbrains:$VERSION"
|
const val extensionsCompose = "com.arkivanov.decompose:extensions-compose-jetbrains:$VERSION"
|
||||||
}
|
}
|
||||||
object MVIKotlin {
|
object MVIKotlin {
|
||||||
private const val VERSION = "2.0.1"
|
private const val VERSION = "2.0.2"
|
||||||
const val rx = "com.arkivanov.mvikotlin:rx:$VERSION"
|
const val rx = "com.arkivanov.mvikotlin:rx:$VERSION"
|
||||||
const val mvikotlin = "com.arkivanov.mvikotlin:mvikotlin:$VERSION"
|
const val mvikotlin = "com.arkivanov.mvikotlin:mvikotlin:$VERSION"
|
||||||
const val mvikotlinMain = "com.arkivanov.mvikotlin:mvikotlin-main:$VERSION"
|
const val mvikotlinMain = "com.arkivanov.mvikotlin:mvikotlin-main:$VERSION"
|
||||||
@ -110,15 +110,6 @@ object MVIKotlin {
|
|||||||
const val mvikotlinTimeTravel = "com.arkivanov.mvikotlin:mvikotlin-timetravel:$VERSION"
|
const val mvikotlinTimeTravel = "com.arkivanov.mvikotlin:mvikotlin-timetravel:$VERSION"
|
||||||
const val mvikotlinExtensionsReaktive = "com.arkivanov.mvikotlin:mvikotlin-extensions-reaktive:$VERSION"
|
const val mvikotlinExtensionsReaktive = "com.arkivanov.mvikotlin:mvikotlin-extensions-reaktive:$VERSION"
|
||||||
}
|
}
|
||||||
object Badoo {
|
|
||||||
object Reaktive {
|
|
||||||
private const val VERSION = "1.1.19"
|
|
||||||
const val reaktive = "com.badoo.reaktive:reaktive:$VERSION"
|
|
||||||
const val reaktiveTesting = "com.badoo.reaktive:reaktive-testing:$VERSION"
|
|
||||||
const val utils = "com.badoo.reaktive:utils:$VERSION"
|
|
||||||
const val coroutinesInterop = "com.badoo.reaktive:coroutines-interop:$VERSION"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
object Ktor {
|
object Ktor {
|
||||||
val clientCore = "io.ktor:ktor-client-core:${Versions.ktor}"
|
val clientCore = "io.ktor:ktor-client-core:${Versions.ktor}"
|
||||||
val clientJson = "io.ktor:ktor-client-json:${Versions.ktor}"
|
val clientJson = "io.ktor:ktor-client-json:${Versions.ktor}"
|
||||||
|
@ -40,6 +40,7 @@ kotlin {
|
|||||||
// nodejs()
|
// nodejs()
|
||||||
binaries.executable()
|
binaries.executable()
|
||||||
}
|
}
|
||||||
|
ios()
|
||||||
sourceSets {
|
sourceSets {
|
||||||
named("commonTest") {
|
named("commonTest") {
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -22,6 +22,15 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
||||||
|
val sdkName: String? = System.getenv("SDK_NAME")
|
||||||
|
val isiOSDevice = sdkName.orEmpty().startsWith("iphoneos")
|
||||||
|
if (isiOSDevice) {
|
||||||
|
iosArm64("ios")
|
||||||
|
} else {
|
||||||
|
iosX64("ios")
|
||||||
|
}
|
||||||
|
|
||||||
jvm("desktop").compilations.all {
|
jvm("desktop").compilations.all {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
useIR = true
|
useIR = true
|
||||||
|
@ -30,5 +30,6 @@ kotlin {
|
|||||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3-native-mt")
|
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3-native-mt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val iosMain by getting
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("multiplatform-setup-test")
|
id("multiplatform-setup")
|
||||||
id("android-setup")
|
id("android-setup")
|
||||||
id("com.squareup.sqldelight")
|
id("com.squareup.sqldelight")
|
||||||
}
|
}
|
||||||
@ -31,7 +31,6 @@ kotlin {
|
|||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":common:data-models"))
|
implementation(project(":common:data-models"))
|
||||||
// implementation(Badoo.Reaktive.reaktive)
|
|
||||||
// SQL Delight
|
// SQL Delight
|
||||||
implementation(SqlDelight.runtime)
|
implementation(SqlDelight.runtime)
|
||||||
implementation(SqlDelight.coroutineExtensions)
|
implementation(SqlDelight.coroutineExtensions)
|
||||||
@ -52,10 +51,10 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*iosMain {
|
val iosMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(Deps.Squareup.SQLDelight.nativeDriver)
|
implementation(SqlDelight.nativeDriver)
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.shabinder.common.database
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import co.touchlab.kermit.NSLogLogger
|
||||||
|
import com.shabinder.database.Database
|
||||||
|
import com.squareup.sqldelight.drivers.native.NativeSqliteDriver
|
||||||
|
|
||||||
|
@Suppress("RedundantNullableReturnType")
|
||||||
|
actual fun createDatabase(): Database? {
|
||||||
|
val driver = NativeSqliteDriver(Database.Schema, "Database.db")
|
||||||
|
return Database(driver)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun getLogger(): Logger = NSLogLogger()
|
@ -20,18 +20,38 @@ plugins {
|
|||||||
id("multiplatform-setup")
|
id("multiplatform-setup")
|
||||||
id("android-setup")
|
id("android-setup")
|
||||||
kotlin("plugin.serialization")
|
kotlin("plugin.serialization")
|
||||||
|
kotlin("native.cocoapods") //version "1.4.32"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
|
||||||
|
cocoapods {
|
||||||
|
// Configure fields required by CocoaPods.
|
||||||
|
summary = "SpotiFlyer Native Module"
|
||||||
|
homepage = "https://github.com/Shabinder/SpotiFlyer"
|
||||||
|
authors = "Shabinder Singh"
|
||||||
|
// You can change the name of the produced framework.
|
||||||
|
// By default, it is the name of the Gradle project.
|
||||||
|
frameworkName = "SpotiFlyer"
|
||||||
|
ios.deploymentTarget = "13.5"
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
pod("TagLibIOS") {
|
||||||
|
version = "~> 0.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":common:data-models"))
|
implementation(project(":common:data-models"))
|
||||||
implementation(project(":common:database"))
|
implementation(project(":common:database"))
|
||||||
implementation(project(":fuzzywuzzy:app"))
|
implementation("org.jetbrains.kotlinx:atomicfu:0.15.2")
|
||||||
implementation("org.jetbrains.kotlinx:atomicfu:0.15.1")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.1.1")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.1.1")
|
||||||
|
implementation("com.shabinder.fuzzywuzzy:fuzzywuzzy:1.0")
|
||||||
implementation(Ktor.clientCore)
|
implementation(Ktor.clientCore)
|
||||||
implementation(Ktor.clientSerialization)
|
implementation(Ktor.clientSerialization)
|
||||||
implementation(Ktor.clientLogging)
|
implementation(Ktor.clientLogging)
|
||||||
@ -72,7 +92,6 @@ kotlin {
|
|||||||
implementation(Ktor.clientJs)
|
implementation(Ktor.clientJs)
|
||||||
implementation(npm("browser-id3-writer", "4.4.0"))
|
implementation(npm("browser-id3-writer", "4.4.0"))
|
||||||
implementation(npm("file-saver", "2.0.4"))
|
implementation(npm("file-saver", "2.0.4"))
|
||||||
// implementation(npm("@types/file-saver","2.0.1",generateExternals = true))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
common/dependency-injection/dependency_injection.podspec
Normal file
46
common/dependency-injection/dependency_injection.podspec
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Pod::Spec.new do |spec|
|
||||||
|
spec.name = 'dependency_injection'
|
||||||
|
spec.version = '1.0'
|
||||||
|
spec.homepage = 'https://github.com/Shabinder/SpotiFlyer'
|
||||||
|
spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" }
|
||||||
|
spec.authors = 'Shabinder Singh'
|
||||||
|
spec.license = ''
|
||||||
|
spec.summary = 'SpotiFlyer Native Module'
|
||||||
|
|
||||||
|
spec.static_framework = true
|
||||||
|
spec.vendored_frameworks = "build/cocoapods/framework/SpotiFlyer.framework"
|
||||||
|
spec.libraries = "c++"
|
||||||
|
spec.module_name = "#{spec.name}_umbrella"
|
||||||
|
|
||||||
|
spec.ios.deployment_target = '13.5'
|
||||||
|
|
||||||
|
spec.dependency 'TagLibIOS', '~> 0.3'
|
||||||
|
|
||||||
|
spec.pod_target_xcconfig = {
|
||||||
|
'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64',
|
||||||
|
'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm',
|
||||||
|
'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x64',
|
||||||
|
'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm',
|
||||||
|
'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64',
|
||||||
|
'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64',
|
||||||
|
'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64'
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.script_phases = [
|
||||||
|
{
|
||||||
|
:name => 'Build dependency_injection',
|
||||||
|
:execution_position => :before_compile,
|
||||||
|
:shell_path => '/bin/sh',
|
||||||
|
:script => <<-SCRIPT
|
||||||
|
set -ev
|
||||||
|
REPO_ROOT="$PODS_TARGET_SRCROOT"
|
||||||
|
"$REPO_ROOT/../../gradlew" -p "$REPO_ROOT" :common:dependency-injection:syncFramework \
|
||||||
|
-Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \
|
||||||
|
-Pkotlin.native.cocoapods.configuration=$CONFIGURATION \
|
||||||
|
-Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \
|
||||||
|
-Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \
|
||||||
|
-Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS"
|
||||||
|
SCRIPT
|
||||||
|
}
|
||||||
|
]
|
||||||
|
end
|
@ -86,18 +86,6 @@ actual class Dir actual constructor(
|
|||||||
File(imageCacheDir()).deleteRecursively()
|
File(imageCacheDir()).deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
actual suspend fun cacheImage(image: Any, path: String) {
|
|
||||||
withContext(Dispatchers.IO){
|
|
||||||
try {
|
|
||||||
FileOutputStream(path).use { out ->
|
|
||||||
(image as? Bitmap)?.compress(Bitmap.CompressFormat.JPEG, 100, out)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
actual suspend fun saveFileWithMetadata(
|
actual suspend fun saveFileWithMetadata(
|
||||||
mp3ByteArray: ByteArray,
|
mp3ByteArray: ByteArray,
|
||||||
@ -178,6 +166,18 @@ actual class Dir actual constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actual suspend fun cacheImage(image: Any, path: String) {
|
||||||
|
withContext(Dispatchers.IO){
|
||||||
|
try {
|
||||||
|
FileOutputStream(path).use { out ->
|
||||||
|
(image as? Bitmap)?.compress(Bitmap.CompressFormat.JPEG, 100, out)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun freshImage(url: String): Bitmap? = withContext(Dispatchers.IO) {
|
private suspend fun freshImage(url: String): Bitmap? = withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val source = URL(url)
|
val source = URL(url)
|
||||||
|
@ -88,7 +88,7 @@ fun Mp3File.removeAllTags(): Mp3File {
|
|||||||
|
|
||||||
fun Mp3File.setId3v1Tags(track: TrackDetails): Mp3File {
|
fun Mp3File.setId3v1Tags(track: TrackDetails): Mp3File {
|
||||||
val id3v1Tag = ID3v1Tag().apply {
|
val id3v1Tag = ID3v1Tag().apply {
|
||||||
artist = track.artists.joinToString(",")
|
artist = track.artists.joinToString(", ")
|
||||||
title = track.title
|
title = track.title
|
||||||
album = track.albumName
|
album = track.albumName
|
||||||
year = track.year
|
year = track.year
|
||||||
@ -102,7 +102,7 @@ fun Mp3File.setId3v1Tags(track: TrackDetails): Mp3File {
|
|||||||
suspend fun Mp3File.setId3v2TagsAndSaveFile(track: TrackDetails) {
|
suspend fun Mp3File.setId3v2TagsAndSaveFile(track: TrackDetails) {
|
||||||
val id3v2Tag = ID3v24Tag().apply {
|
val id3v2Tag = ID3v24Tag().apply {
|
||||||
|
|
||||||
artist = track.artists.joinToString(",")
|
artist = track.artists.joinToString(", ")
|
||||||
title = track.title
|
title = track.title
|
||||||
album = track.albumName
|
album = track.albumName
|
||||||
year = track.year
|
year = track.year
|
||||||
|
@ -34,7 +34,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
expect class Dir(
|
expect class Dir (
|
||||||
logger: Kermit,
|
logger: Kermit,
|
||||||
database: Database? = createDatabase(),
|
database: Database? = createDatabase(),
|
||||||
) {
|
) {
|
||||||
@ -89,6 +89,7 @@ suspend fun downloadByteArray(
|
|||||||
fun getNameURL(url: String): String {
|
fun getNameURL(url: String): String {
|
||||||
return url.substring(url.lastIndexOf('/', url.lastIndexOf('/') - 1) + 1, url.length).replace('/', '_')
|
return url.substring(url.lastIndexOf('/', url.lastIndexOf('/') - 1) + 1, url.length).replace('/', '_')
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call this function at startup!
|
* Call this function at startup!
|
||||||
* */
|
* */
|
||||||
@ -100,6 +101,7 @@ fun Dir.createDirectories() {
|
|||||||
createDirectory(defaultDir() + "Playlists/")
|
createDirectory(defaultDir() + "Playlists/")
|
||||||
createDirectory(defaultDir() + "YT_Downloads/")
|
createDirectory(defaultDir() + "YT_Downloads/")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Dir.finalOutputDir(itemName: String, type: String, subFolder: String, defaultDir: String, extension: String = ".mp3"): String =
|
fun Dir.finalOutputDir(itemName: String, type: String, subFolder: String, defaultDir: String, extension: String = ".mp3"): String =
|
||||||
defaultDir + removeIllegalChars(type) + this.fileSeparator() +
|
defaultDir + removeIllegalChars(type) + this.fileSeparator() +
|
||||||
if (subFolder.isEmpty())"" else { removeIllegalChars(subFolder) + this.fileSeparator() } +
|
if (subFolder.isEmpty())"" else { removeIllegalChars(subFolder) + this.fileSeparator() } +
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.shabinder.common.di
|
||||||
|
|
||||||
|
import com.shabinder.common.models.AllPlatforms
|
||||||
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
actual fun queryActiveTracks() {}
|
||||||
|
|
||||||
|
actual fun openPlatform(packageID: String, platformLink: String) {}
|
||||||
|
|
||||||
|
actual fun shareApp() {}
|
||||||
|
|
||||||
|
actual fun giveDonation() {}
|
||||||
|
|
||||||
|
actual val dispatcherIO: CoroutineDispatcher = Dispatchers.Default
|
||||||
|
|
||||||
|
actual val isInternetAvailable: Boolean
|
||||||
|
get() = runBlocking { isInternetAccessible() }
|
||||||
|
|
||||||
|
actual val currentPlatform: AllPlatforms = AllPlatforms.Native
|
||||||
|
|
||||||
|
actual suspend fun downloadTracks(
|
||||||
|
list: List<TrackDetails>,
|
||||||
|
fetcher: FetchPlatformQueryResult,
|
||||||
|
dir: Dir
|
||||||
|
) {
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
}
|
@ -0,0 +1,146 @@
|
|||||||
|
package com.shabinder.common.di
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Kermit
|
||||||
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import com.shabinder.database.Database
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import platform.Foundation.*
|
||||||
|
import platform.UIKit.UIImage
|
||||||
|
import platform.UIKit.UIImageJPEGRepresentation
|
||||||
|
import cocoapods.TagLibIOS.TLAudio
|
||||||
|
|
||||||
|
actual class Dir actual constructor(
|
||||||
|
private val logger: Kermit,
|
||||||
|
private val database: Database?
|
||||||
|
) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
createDirectories()
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun isPresent(path: String): Boolean = NSFileManager.defaultManager.fileExistsAtPath(path)
|
||||||
|
|
||||||
|
actual fun fileSeparator(): String = "/"
|
||||||
|
|
||||||
|
// TODO Error Handling
|
||||||
|
actual fun defaultDir(): String = defaultDirURL.path!!
|
||||||
|
|
||||||
|
val defaultDirURL: NSURL by lazy {
|
||||||
|
val musicDir = NSFileManager.defaultManager.URLForDirectory(NSMusicDirectory, NSUserDomainMask,null,true,null)!!
|
||||||
|
musicDir.URLByAppendingPathComponent("SpotiFlyer",true)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun imageCacheDir(): String = imageCacheURL.path!!
|
||||||
|
|
||||||
|
val imageCacheURL: NSURL by lazy {
|
||||||
|
val cacheDir = NSFileManager.defaultManager.URLForDirectory(NSCachesDirectory, NSUserDomainMask,null,true,null)
|
||||||
|
cacheDir?.URLByAppendingPathComponent("SpotiFlyer",true)!!
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun createDirectory(dirPath: String) {
|
||||||
|
try {
|
||||||
|
NSFileManager.defaultManager.createDirectoryAtPath(dirPath,true,null,null)
|
||||||
|
} catch (e:Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createDirectory(dirURL: NSURL) {
|
||||||
|
try {
|
||||||
|
NSFileManager.defaultManager.createDirectoryAtURL(dirURL,true,null,null)
|
||||||
|
} catch (e:Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun cacheImage(image: Any, path: String) {
|
||||||
|
try {
|
||||||
|
(image as? UIImage)?.let {
|
||||||
|
// We Will Be Using JPEG as default format everywhere
|
||||||
|
UIImageJPEGRepresentation(it,1.0)
|
||||||
|
?.writeToFile(path,true)
|
||||||
|
}
|
||||||
|
}catch (e:Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun loadImage(url: String): Picture {
|
||||||
|
return try {
|
||||||
|
val cachePath = imageCacheURL.URLByAppendingPathComponent(getNameURL(url))
|
||||||
|
Picture(image = cachePath?.path?.let { loadCachedImage(it) } ?: loadFreshImage(url))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Picture(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadCachedImage(filePath: String): UIImage? {
|
||||||
|
return try {
|
||||||
|
UIImage.imageWithContentsOfFile(filePath)
|
||||||
|
}catch (e:Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun loadFreshImage(url: String):UIImage? {
|
||||||
|
return try {
|
||||||
|
val nsURL = NSURL(url)
|
||||||
|
val data = NSURLConnection.sendSynchronousRequest(NSURLRequest.requestWithURL(nsURL),null,null)
|
||||||
|
if (data != null) {
|
||||||
|
UIImage.imageWithData(data)?.also {
|
||||||
|
GlobalScope.launch {
|
||||||
|
cacheImage(it, imageCacheDir() + getNameURL(url))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else null
|
||||||
|
}catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun clearCache() {
|
||||||
|
try {
|
||||||
|
val fileManager = NSFileManager.defaultManager
|
||||||
|
val paths = fileManager.contentsOfDirectoryAtURL(imageCacheURL,
|
||||||
|
null,
|
||||||
|
NSDirectoryEnumerationSkipsHiddenFiles,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
paths?.forEach {
|
||||||
|
(it as? NSURL)?.let { nsURL ->
|
||||||
|
// Lets Remove Cached File
|
||||||
|
fileManager.removeItemAtURL(nsURL,null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
actual suspend fun saveFileWithMetadata(
|
||||||
|
mp3ByteArray: ByteArray,
|
||||||
|
trackDetails: TrackDetails
|
||||||
|
) {
|
||||||
|
when (trackDetails.outputFilePath.substringAfterLast('.')) {
|
||||||
|
".mp3" -> {
|
||||||
|
val file = TLAudio(trackDetails.outputFilePath)
|
||||||
|
file.addTagsAndSave(
|
||||||
|
trackDetails,
|
||||||
|
this::loadCachedImage,
|
||||||
|
this::addToLibrary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
actual fun addToLibrary(path: String) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
actual val db: Database? = database
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.shabinder.common.di
|
||||||
|
|
||||||
|
import platform.UIKit.UIImage
|
||||||
|
|
||||||
|
actual data class Picture(
|
||||||
|
val image: UIImage?
|
||||||
|
)
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.shabinder.common.di
|
||||||
|
|
||||||
|
import cocoapods.TagLibIOS.TLAudio
|
||||||
|
import com.shabinder.common.models.TrackDetails
|
||||||
|
import platform.Foundation.NSNumber
|
||||||
|
import platform.UIKit.UIImage
|
||||||
|
import platform.UIKit.UIImageJPEGRepresentation
|
||||||
|
|
||||||
|
suspend fun TLAudio.addTagsAndSave(
|
||||||
|
trackDetails: TrackDetails,
|
||||||
|
loadCachedImage:(path:String)->UIImage?,
|
||||||
|
addToLibrary:(path:String)->Unit
|
||||||
|
) {
|
||||||
|
title = trackDetails.title
|
||||||
|
artist = trackDetails.artists.joinToString(", ")
|
||||||
|
album = trackDetails.albumName
|
||||||
|
comment = trackDetails.comment
|
||||||
|
try { trackDetails.year?.substring(0, 4)?.toInt()?.let { year = NSNumber(it) } } catch (e: Exception) {}
|
||||||
|
try {
|
||||||
|
val image = loadCachedImage(trackDetails.albumArtPath)
|
||||||
|
if (image != null) {
|
||||||
|
setFrontCoverPicture(UIImageJPEGRepresentation(image,1.0))
|
||||||
|
save()
|
||||||
|
addToLibrary(trackDetails.outputFilePath)
|
||||||
|
}
|
||||||
|
throw Exception("Cached Image not Present,Trying to Download...")
|
||||||
|
} catch (e: Exception){
|
||||||
|
e.printStackTrace()
|
||||||
|
try {
|
||||||
|
downloadByteArray(trackDetails.albumArtURL)?.toNSData()?.also {
|
||||||
|
setFrontCoverPicture(it)
|
||||||
|
save()
|
||||||
|
addToLibrary(trackDetails.outputFilePath)
|
||||||
|
}
|
||||||
|
} catch (e: Exception){ e.printStackTrace() }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.shabinder.common.di
|
||||||
|
|
||||||
|
import kotlinx.cinterop.memScoped
|
||||||
|
import kotlinx.cinterop.refTo
|
||||||
|
import kotlinx.cinterop.toCValues
|
||||||
|
import platform.Foundation.NSData
|
||||||
|
import platform.Foundation.create
|
||||||
|
import platform.posix.memcpy
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
fun ByteArray.toNSData(): NSData = memScoped {
|
||||||
|
return NSData.create(
|
||||||
|
bytes = toCValues().getPointer(this),
|
||||||
|
length = size.toULong()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalUnsignedTypes::class)
|
||||||
|
fun NSData.toByteArray(): ByteArray = memScoped {
|
||||||
|
val size = length.toInt()
|
||||||
|
val nsData = ByteArray(size)
|
||||||
|
memcpy(nsData.refTo(0), bytes, size.toULong())
|
||||||
|
return nsData
|
||||||
|
}
|
@ -1,42 +0,0 @@
|
|||||||
# Java Gradle CircleCI 2.0 configuration file
|
|
||||||
#
|
|
||||||
# Check https://circleci.com/docs/2.0/language-java/ for more details
|
|
||||||
#
|
|
||||||
version: 2
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
docker:
|
|
||||||
# specify the version you desire here
|
|
||||||
- image: circleci/openjdk:8-jdk
|
|
||||||
|
|
||||||
# Specify service dependencies here if necessary
|
|
||||||
# CircleCI maintains a library of pre-built images
|
|
||||||
# documented at https://circleci.com/docs/2.0/circleci-images/
|
|
||||||
# - image: circleci/postgres:9.4
|
|
||||||
|
|
||||||
working_directory: ~/repo
|
|
||||||
|
|
||||||
environment:
|
|
||||||
# Customize the JVM maximum heap limit
|
|
||||||
JVM_OPTS: -Xmx3200m
|
|
||||||
TERM: dumb
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
|
|
||||||
# Download and cache dependencies
|
|
||||||
- restore_cache:
|
|
||||||
keys:
|
|
||||||
- v1-dependencies-{{ checksum "build.gradle" }}
|
|
||||||
# fallback to using the latest cache if no exact match is found
|
|
||||||
- v1-dependencies-
|
|
||||||
|
|
||||||
- run: gradle dependencies
|
|
||||||
|
|
||||||
- save_cache:
|
|
||||||
paths:
|
|
||||||
- ~/.gradle
|
|
||||||
key: v1-dependencies-{{ checksum "build.gradle" }}
|
|
||||||
|
|
||||||
# run tests!
|
|
||||||
- run: gradle app:jvmTest
|
|
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
@ -1,44 +0,0 @@
|
|||||||
# FuzzyWuzzy-Kotlin
|
|
||||||
|
|
||||||
![badge][badge-android]
|
|
||||||
![badge][badge-native]
|
|
||||||
![badge][badge-js]
|
|
||||||
![badge][badge-jvm]
|
|
||||||
![badge][badge-linux]
|
|
||||||
![badge][badge-windows]
|
|
||||||
![badge][badge-mac]
|
|
||||||
![badge][badge-wasm]
|
|
||||||
|
|
||||||
[![CircleCI](https://circleci.com/gh/willowtreeapps/fuzzywuzzy-kotlin.svg?style=svg)](https://circleci.com/gh/willowtreeapps/fuzzywuzzy-kotlin)
|
|
||||||
|
|
||||||
Fuzzy string matching for Kotlin (JVM, iOS) - fork of [the Java fork](https://github.com/xdrop/fuzzywuzzy) of of [Fuzzy Wuzzy Python lib](https://github.com/seatgeek/fuzzywuzzy). For use in on JVM, Android, or Kotlin Multiplatform projects (JVM/Android, iOS, mac, linux)
|
|
||||||
|
|
||||||
Useful for selecting the closest matching string from a collection of strings. Various algorithms are available.
|
|
||||||
|
|
||||||
See Java repo or Python repo for usage.
|
|
||||||
|
|
||||||
To add to project in the common module add the dependency:
|
|
||||||
|
|
||||||
```
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation "com.willowtreeapps:fuzzywuzzy-kotlin:0.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
[badge-android]: http://img.shields.io/badge/platform-android-brightgreen.svg?style=flat
|
|
||||||
[badge-native]: http://img.shields.io/badge/platform-native-lightgrey.svg?style=flat
|
|
||||||
[badge-native]: http://img.shields.io/badge/platform-native-lightgrey.svg?style=flat
|
|
||||||
[badge-js]: http://img.shields.io/badge/platform-js-yellow.svg?style=flat
|
|
||||||
[badge-js]: http://img.shields.io/badge/platform-js-yellow.svg?style=flat
|
|
||||||
[badge-jvm]: http://img.shields.io/badge/platform-jvm-orange.svg?style=flat
|
|
||||||
[badge-jvm]: http://img.shields.io/badge/platform-jvm-orange.svg?style=flat
|
|
||||||
[badge-linux]: http://img.shields.io/badge/platform-linux-important.svg?style=flat
|
|
||||||
[badge-linux]: http://img.shields.io/badge/platform-linux-important.svg?style=flat
|
|
||||||
[badge-windows]: http://img.shields.io/badge/platform-windows-informational.svg?style=flat
|
|
||||||
[badge-windows]: http://img.shields.io/badge/platform-windows-informational.svg?style=flat
|
|
||||||
[badge-mac]: http://img.shields.io/badge/platform-macos-lightgrey.svg?style=flat
|
|
||||||
[badge-mac]: http://img.shields.io/badge/platform-macos-lightgrey.svg?style=flat
|
|
||||||
[badge-wasm]: https://img.shields.io/badge/platform-wasm-darkblue.svg?style=flat
|
|
@ -1,215 +0,0 @@
|
|||||||
apply plugin: 'java'
|
|
||||||
apply plugin: 'kotlin-multiplatform'
|
|
||||||
apply plugin: 'com.moowork.node'
|
|
||||||
|
|
||||||
archivesBaseName = 'fuzzywuzzy-kotlin'
|
|
||||||
|
|
||||||
group 'com.willowtreeapps'
|
|
||||||
version '0.1.1'
|
|
||||||
final nodeVersion = '11.2.0'
|
|
||||||
final nodeWorkingDir = project.buildDir
|
|
||||||
final nodeModules = "$nodeWorkingDir/node_modules"
|
|
||||||
final mochaVersion = '5.2.0'
|
|
||||||
final pathSeparator = System.properties["path.separator"]
|
|
||||||
|
|
||||||
kotlin {
|
|
||||||
jvm()
|
|
||||||
js() {
|
|
||||||
browser()
|
|
||||||
[compileKotlinJs, compileTestKotlinJs].each { configuration ->
|
|
||||||
configuration.kotlinOptions {
|
|
||||||
moduleKind = 'umd'
|
|
||||||
sourceMap = true
|
|
||||||
metaInfo = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
wasm32("wasm")
|
|
||||||
iosArm64("ios")
|
|
||||||
iosX64("iosSim")
|
|
||||||
macosX64("macos")
|
|
||||||
mingwX64("win")
|
|
||||||
linuxArm32Hfp("linArm32")
|
|
||||||
linuxMips32("linMips32")
|
|
||||||
linuxMipsel32("linMipsel32")
|
|
||||||
linuxX64("lin64")
|
|
||||||
*/
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("stdlib-common")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jvmMain {
|
|
||||||
kotlin.srcDir('src/jvmMain/kotlin')
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("stdlib")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsMain {
|
|
||||||
kotlin.srcDir('src/jsMain/kotlin')
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("stdlib-js")
|
|
||||||
}
|
|
||||||
compileKotlinJs {
|
|
||||||
kotlinOptions.metaInfo = true
|
|
||||||
kotlinOptions.sourceMap = true
|
|
||||||
kotlinOptions.suppressWarnings = true
|
|
||||||
kotlinOptions.verbose = true
|
|
||||||
kotlinOptions.main = "call"
|
|
||||||
kotlinOptions.moduleKind = "umd"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
commonTest {
|
|
||||||
kotlin.srcDir('src/test')
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("test-common")
|
|
||||||
implementation kotlin("test-annotations-common")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jsTest {
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("test-js")
|
|
||||||
implementation kotlin("stdlib-js")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jvmTest {
|
|
||||||
dependencies {
|
|
||||||
implementation kotlin("test")
|
|
||||||
implementation kotlin("test-junit")
|
|
||||||
implementation 'junit:junit:4.13.2'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*nativeMain {
|
|
||||||
kotlin.srcDir('src/nativeMain/kotlin')
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//iosSimMain.dependsOn iosMain
|
|
||||||
//iosSimTest.dependsOn iosTest
|
|
||||||
|
|
||||||
/*configure([targets.ios, targets.iosSim, targets.macos, targets.win, targets.linArm32, targets.linMips32, targets.linMipsel32, targets.lin64]) {
|
|
||||||
compilations.main.source(sourceSets.nativeMain)
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
//Workaround to copy kotlin libraries so they are visible during testing
|
|
||||||
//def jsLibDir = "$compileKotlinJs.destinationDir/lib"
|
|
||||||
//def jsTestLibDir = "$compileTestKotlinJs.destinationDir/lib"
|
|
||||||
|
|
||||||
//uncomment below to test JS. This conflicts with iOS config
|
|
||||||
/*
|
|
||||||
configurations {
|
|
||||||
jsLibs
|
|
||||||
jsTestLibs
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
jsLibs "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinRuntimeVersion"
|
|
||||||
jsTestLibs "org.jetbrains.kotlin:kotlin-test-js:$kotlinRuntimeVersion"
|
|
||||||
}
|
|
||||||
|
|
||||||
task copyJsDependencies(type: Copy, dependsOn: compileKotlinJs) {
|
|
||||||
configurations.jsLibs.each {
|
|
||||||
from zipTree(it.absolutePath).matching { include '*.js'}
|
|
||||||
}
|
|
||||||
into jsLibDir
|
|
||||||
}
|
|
||||||
jsMainClasses.dependsOn copyJsDependencies
|
|
||||||
task copyJsTestDependencies(type: Copy) {
|
|
||||||
configurations.jsTestLibs.each {
|
|
||||||
from zipTree(it.absolutePath).matching { include '*.js'}
|
|
||||||
}
|
|
||||||
into jsTestLibDir
|
|
||||||
}
|
|
||||||
jsTestClasses.dependsOn copyJsTestDependencies
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
node {
|
|
||||||
version = nodeVersion
|
|
||||||
download = true
|
|
||||||
workDir = file("$project.buildDir/nodejs")
|
|
||||||
nodeModulesDir = file(nodeWorkingDir)
|
|
||||||
}
|
|
||||||
task installMocha(type: NpmTask, group: 'npm') {
|
|
||||||
outputs.dir "$nodeModules/mocha"
|
|
||||||
args = ['install', "mocha@$mochaVersion"]
|
|
||||||
}
|
|
||||||
task runMocha(type: NodeTask, dependsOn: [installMocha, jsMainClasses, jsTestClasses], group: 'npm') {
|
|
||||||
environment = ["NODE_PATH": "$jsLibDir$pathSeparator$jsTestLibDir$pathSeparator$compileKotlinJs.destinationDir"]
|
|
||||||
script = file("$nodeWorkingDir/node_modules/mocha/bin/mocha")
|
|
||||||
args = [compileTestKotlinJs.outputFile]
|
|
||||||
}
|
|
||||||
//Use mocha to run js tests
|
|
||||||
jsTest.dependsOn runMocha
|
|
||||||
|
|
||||||
task iosTest(dependsOn: 'linkTestDebugExecutableIosSim') {
|
|
||||||
doLast {
|
|
||||||
def binary = kotlin.targets.iosSim.compilations.test.getBinary('EXECUTABLE', 'DEBUG')
|
|
||||||
exec {
|
|
||||||
commandLine 'xcrun', 'simctl', 'spawn', "iPhone XR", binary.absolutePath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.check.dependsOn iosTest
|
|
||||||
|
|
||||||
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
|
|
||||||
//configurations {
|
|
||||||
// compileClasspath
|
|
||||||
//}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
// Alias the task names we use elsewhere to the new task names.
|
|
||||||
tasks.create('installMP').dependsOn('publishKotlinMultiplatformPublicationToMavenLocal')
|
|
||||||
tasks.create('installLocally') {
|
|
||||||
dependsOn 'publishKotlinMultiplatformPublicationToTestRepository'
|
|
||||||
dependsOn 'publishJvmPublicationToTestRepository'
|
|
||||||
dependsOn 'publishJsPublicationToTestRepository'
|
|
||||||
dependsOn 'publishMetadataPublicationToTestRepository'
|
|
||||||
}
|
|
||||||
tasks.create('installIosLocally') {
|
|
||||||
dependsOn 'publishKotlinMultiplatformPublicationToTestRepository'
|
|
||||||
dependsOn 'publishIosArm32PublicationToTestRepository'
|
|
||||||
dependsOn 'publishIosArm64PublicationToTestRepository'
|
|
||||||
dependsOn 'publishIosX64PublicationToTestRepository'
|
|
||||||
dependsOn 'publishMetadataPublicationToTestRepository'
|
|
||||||
}
|
|
||||||
// NOTE: We do not alias uploadArchives because CI runs it on Linux and we only want to run it on Mac OS.
|
|
||||||
//tasks.create('uploadArchives').dependsOn('publishKotlinMultiplatformPublicationToMavenRepository')
|
|
||||||
}
|
|
||||||
|
|
||||||
apply from: rootProject.file('fuzzywuzzy/gradle/publish.gradle')
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
// Rewrite all artifacts from using the project name to just 'runtime'.
|
|
||||||
artifactId = artifactId.replace(project.name, 'fuzzywuzzy-kotlin')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
853
fuzzywuzzy/app/package-lock.json
generated
853
fuzzywuzzy/app/package-lock.json
generated
@ -1,853 +0,0 @@
|
|||||||
{
|
|
||||||
"requires": true,
|
|
||||||
"lockfileVersion": 1,
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-colors": {
|
|
||||||
"version": "3.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
|
|
||||||
"integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw=="
|
|
||||||
},
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
|
||||||
"version": "3.2.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
|
||||||
"requires": {
|
|
||||||
"color-convert": "1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"argparse": {
|
|
||||||
"version": "1.0.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
|
||||||
"requires": {
|
|
||||||
"sprintf-js": "1.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"balanced-match": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"browser-stdout": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
|
|
||||||
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
|
|
||||||
},
|
|
||||||
"camelcase": {
|
|
||||||
"version": "5.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
|
||||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "3.2.1",
|
|
||||||
"escape-string-regexp": "1.0.5",
|
|
||||||
"supports-color": "5.5.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cliui": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
|
|
||||||
"requires": {
|
|
||||||
"string-width": "2.1.1",
|
|
||||||
"strip-ansi": "4.0.0",
|
|
||||||
"wrap-ansi": "2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"code-point-at": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
|
||||||
},
|
|
||||||
"color-convert": {
|
|
||||||
"version": "1.9.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
|
||||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
|
||||||
"requires": {
|
|
||||||
"color-name": "1.1.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"color-name": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
|
||||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
|
||||||
},
|
|
||||||
"concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
|
||||||
},
|
|
||||||
"cross-spawn": {
|
|
||||||
"version": "6.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
|
||||||
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
|
||||||
"requires": {
|
|
||||||
"nice-try": "1.0.5",
|
|
||||||
"path-key": "2.0.1",
|
|
||||||
"semver": "5.7.0",
|
|
||||||
"shebang-command": "1.2.0",
|
|
||||||
"which": "1.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"debug": {
|
|
||||||
"version": "3.2.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
|
||||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
|
||||||
"requires": {
|
|
||||||
"ms": "2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"decamelize": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
|
||||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
|
||||||
},
|
|
||||||
"define-properties": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
|
||||||
"requires": {
|
|
||||||
"object-keys": "1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"diff": {
|
|
||||||
"version": "3.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
|
|
||||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
|
|
||||||
},
|
|
||||||
"emoji-regex": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
|
|
||||||
},
|
|
||||||
"end-of-stream": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
|
|
||||||
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
|
|
||||||
"requires": {
|
|
||||||
"once": "1.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"es-abstract": {
|
|
||||||
"version": "1.13.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
|
|
||||||
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
|
|
||||||
"requires": {
|
|
||||||
"es-to-primitive": "1.2.0",
|
|
||||||
"function-bind": "1.1.1",
|
|
||||||
"has": "1.0.3",
|
|
||||||
"is-callable": "1.1.4",
|
|
||||||
"is-regex": "1.0.4",
|
|
||||||
"object-keys": "1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"es-to-primitive": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
|
|
||||||
"requires": {
|
|
||||||
"is-callable": "1.1.4",
|
|
||||||
"is-date-object": "1.0.1",
|
|
||||||
"is-symbol": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"escape-string-regexp": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
|
||||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
|
||||||
},
|
|
||||||
"esprima": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
|
||||||
},
|
|
||||||
"execa": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
|
||||||
"requires": {
|
|
||||||
"cross-spawn": "6.0.5",
|
|
||||||
"get-stream": "4.1.0",
|
|
||||||
"is-stream": "1.1.0",
|
|
||||||
"npm-run-path": "2.0.2",
|
|
||||||
"p-finally": "1.0.0",
|
|
||||||
"signal-exit": "3.0.2",
|
|
||||||
"strip-eof": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"find-up": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
|
||||||
"requires": {
|
|
||||||
"locate-path": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"flat": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
|
|
||||||
"requires": {
|
|
||||||
"is-buffer": "2.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fs.realpath": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
|
||||||
},
|
|
||||||
"function-bind": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
|
||||||
},
|
|
||||||
"get-caller-file": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
|
||||||
},
|
|
||||||
"get-stream": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
|
||||||
"requires": {
|
|
||||||
"pump": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"glob": {
|
|
||||||
"version": "7.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
|
|
||||||
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
|
|
||||||
"requires": {
|
|
||||||
"fs.realpath": "1.0.0",
|
|
||||||
"inflight": "1.0.6",
|
|
||||||
"inherits": "2.0.3",
|
|
||||||
"minimatch": "3.0.4",
|
|
||||||
"once": "1.4.0",
|
|
||||||
"path-is-absolute": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"growl": {
|
|
||||||
"version": "1.10.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
|
|
||||||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
|
|
||||||
},
|
|
||||||
"has": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
|
||||||
"requires": {
|
|
||||||
"function-bind": "1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"has-flag": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
|
||||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
|
||||||
},
|
|
||||||
"has-symbols": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
|
|
||||||
},
|
|
||||||
"he": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
|
||||||
},
|
|
||||||
"inflight": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
|
||||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
|
||||||
"requires": {
|
|
||||||
"once": "1.4.0",
|
|
||||||
"wrappy": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inherits": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
|
||||||
},
|
|
||||||
"invert-kv": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
|
|
||||||
},
|
|
||||||
"is-buffer": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
|
|
||||||
},
|
|
||||||
"is-callable": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
|
|
||||||
},
|
|
||||||
"is-date-object": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
|
|
||||||
},
|
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
|
||||||
},
|
|
||||||
"is-regex": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
|
|
||||||
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
|
|
||||||
"requires": {
|
|
||||||
"has": "1.0.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is-stream": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
|
||||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
|
||||||
},
|
|
||||||
"is-symbol": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
|
|
||||||
"requires": {
|
|
||||||
"has-symbols": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"isexe": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
|
||||||
},
|
|
||||||
"js-yaml": {
|
|
||||||
"version": "3.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
|
||||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
|
||||||
"requires": {
|
|
||||||
"argparse": "1.0.10",
|
|
||||||
"esprima": "4.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lcid": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
|
|
||||||
"requires": {
|
|
||||||
"invert-kv": "2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"locate-path": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
|
||||||
"requires": {
|
|
||||||
"p-locate": "3.0.0",
|
|
||||||
"path-exists": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lodash": {
|
|
||||||
"version": "4.17.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
|
||||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
|
||||||
},
|
|
||||||
"log-symbols": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
|
|
||||||
"requires": {
|
|
||||||
"chalk": "2.4.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"map-age-cleaner": {
|
|
||||||
"version": "0.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
|
|
||||||
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
|
|
||||||
"requires": {
|
|
||||||
"p-defer": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mem": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
|
|
||||||
"requires": {
|
|
||||||
"map-age-cleaner": "0.1.3",
|
|
||||||
"mimic-fn": "2.1.0",
|
|
||||||
"p-is-promise": "2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mimic-fn": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "1.1.11"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimist": {
|
|
||||||
"version": "0.0.8",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
|
|
||||||
},
|
|
||||||
"mkdirp": {
|
|
||||||
"version": "0.5.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
|
||||||
"requires": {
|
|
||||||
"minimist": "0.0.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mocha": {
|
|
||||||
"version": "6.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz",
|
|
||||||
"integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-colors": "3.2.3",
|
|
||||||
"browser-stdout": "1.3.1",
|
|
||||||
"debug": "3.2.6",
|
|
||||||
"diff": "3.5.0",
|
|
||||||
"escape-string-regexp": "1.0.5",
|
|
||||||
"find-up": "3.0.0",
|
|
||||||
"glob": "7.1.3",
|
|
||||||
"growl": "1.10.5",
|
|
||||||
"he": "1.2.0",
|
|
||||||
"js-yaml": "3.13.1",
|
|
||||||
"log-symbols": "2.2.0",
|
|
||||||
"minimatch": "3.0.4",
|
|
||||||
"mkdirp": "0.5.1",
|
|
||||||
"ms": "2.1.1",
|
|
||||||
"node-environment-flags": "1.0.5",
|
|
||||||
"object.assign": "4.1.0",
|
|
||||||
"strip-json-comments": "2.0.1",
|
|
||||||
"supports-color": "6.0.0",
|
|
||||||
"which": "1.3.1",
|
|
||||||
"wide-align": "1.1.3",
|
|
||||||
"yargs": "13.2.2",
|
|
||||||
"yargs-parser": "13.0.0",
|
|
||||||
"yargs-unparser": "1.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
|
||||||
},
|
|
||||||
"nice-try": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
|
|
||||||
},
|
|
||||||
"node-environment-flags": {
|
|
||||||
"version": "1.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
|
|
||||||
"integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
|
|
||||||
"requires": {
|
|
||||||
"object.getownpropertydescriptors": "2.0.3",
|
|
||||||
"semver": "5.7.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"npm-run-path": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
|
||||||
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
|
|
||||||
"requires": {
|
|
||||||
"path-key": "2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"number-is-nan": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
|
||||||
},
|
|
||||||
"object-keys": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
|
||||||
},
|
|
||||||
"object.assign": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
|
||||||
"requires": {
|
|
||||||
"define-properties": "1.1.3",
|
|
||||||
"function-bind": "1.1.1",
|
|
||||||
"has-symbols": "1.0.0",
|
|
||||||
"object-keys": "1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"object.getownpropertydescriptors": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
|
||||||
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
|
|
||||||
"requires": {
|
|
||||||
"define-properties": "1.1.3",
|
|
||||||
"es-abstract": "1.13.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"once": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
|
||||||
"requires": {
|
|
||||||
"wrappy": "1.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"os-locale": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
|
|
||||||
"requires": {
|
|
||||||
"execa": "1.0.0",
|
|
||||||
"lcid": "2.0.0",
|
|
||||||
"mem": "4.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"p-defer": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
|
|
||||||
},
|
|
||||||
"p-finally": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
|
|
||||||
},
|
|
||||||
"p-is-promise": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
|
|
||||||
},
|
|
||||||
"p-limit": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
|
|
||||||
"requires": {
|
|
||||||
"p-try": "2.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"p-locate": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
|
||||||
"requires": {
|
|
||||||
"p-limit": "2.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"p-try": {
|
|
||||||
"version": "2.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
|
||||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
|
||||||
},
|
|
||||||
"path-exists": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
|
||||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
|
|
||||||
},
|
|
||||||
"path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
|
||||||
},
|
|
||||||
"path-key": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
|
||||||
},
|
|
||||||
"pump": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
|
||||||
"requires": {
|
|
||||||
"end-of-stream": "1.4.1",
|
|
||||||
"once": "1.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"require-directory": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
|
||||||
},
|
|
||||||
"require-main-filename": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
|
||||||
},
|
|
||||||
"semver": {
|
|
||||||
"version": "5.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
|
|
||||||
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
|
|
||||||
},
|
|
||||||
"set-blocking": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
|
||||||
},
|
|
||||||
"shebang-command": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
|
||||||
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
|
|
||||||
"requires": {
|
|
||||||
"shebang-regex": "1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shebang-regex": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
|
|
||||||
},
|
|
||||||
"signal-exit": {
|
|
||||||
"version": "3.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
|
||||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
|
|
||||||
},
|
|
||||||
"sprintf-js": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
|
||||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
|
||||||
"requires": {
|
|
||||||
"is-fullwidth-code-point": "2.0.0",
|
|
||||||
"strip-ansi": "4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
|
||||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-eof": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
|
||||||
},
|
|
||||||
"strip-json-comments": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
|
||||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
|
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"version": "1.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
|
||||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
|
||||||
"requires": {
|
|
||||||
"isexe": "2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"which-module": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
|
||||||
},
|
|
||||||
"wide-align": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
|
||||||
"requires": {
|
|
||||||
"string-width": "2.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrap-ansi": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
|
||||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
|
||||||
"requires": {
|
|
||||||
"string-width": "1.0.2",
|
|
||||||
"strip-ansi": "3.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
|
||||||
},
|
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
|
||||||
"requires": {
|
|
||||||
"number-is-nan": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
|
||||||
"requires": {
|
|
||||||
"code-point-at": "1.1.0",
|
|
||||||
"is-fullwidth-code-point": "1.0.0",
|
|
||||||
"strip-ansi": "3.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "2.1.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrappy": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
|
||||||
},
|
|
||||||
"y18n": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
|
||||||
},
|
|
||||||
"yargs": {
|
|
||||||
"version": "13.2.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
|
|
||||||
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
|
|
||||||
"requires": {
|
|
||||||
"cliui": "4.1.0",
|
|
||||||
"find-up": "3.0.0",
|
|
||||||
"get-caller-file": "2.0.5",
|
|
||||||
"os-locale": "3.1.0",
|
|
||||||
"require-directory": "2.1.1",
|
|
||||||
"require-main-filename": "2.0.0",
|
|
||||||
"set-blocking": "2.0.0",
|
|
||||||
"string-width": "3.1.0",
|
|
||||||
"which-module": "2.0.0",
|
|
||||||
"y18n": "4.0.0",
|
|
||||||
"yargs-parser": "13.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-regex": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
|
|
||||||
},
|
|
||||||
"string-width": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
|
||||||
"requires": {
|
|
||||||
"emoji-regex": "7.0.3",
|
|
||||||
"is-fullwidth-code-point": "2.0.0",
|
|
||||||
"strip-ansi": "5.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-ansi": {
|
|
||||||
"version": "5.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
|
||||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "4.1.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yargs-parser": {
|
|
||||||
"version": "13.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
|
|
||||||
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
|
|
||||||
"requires": {
|
|
||||||
"camelcase": "5.3.1",
|
|
||||||
"decamelize": "1.2.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yargs-unparser": {
|
|
||||||
"version": "1.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
|
|
||||||
"integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
|
|
||||||
"requires": {
|
|
||||||
"flat": "4.1.0",
|
|
||||||
"lodash": "4.17.11",
|
|
||||||
"yargs": "12.0.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"get-caller-file": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
|
|
||||||
},
|
|
||||||
"require-main-filename": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
|
|
||||||
},
|
|
||||||
"yargs": {
|
|
||||||
"version": "12.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
|
|
||||||
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
|
|
||||||
"requires": {
|
|
||||||
"cliui": "4.1.0",
|
|
||||||
"decamelize": "1.2.0",
|
|
||||||
"find-up": "3.0.0",
|
|
||||||
"get-caller-file": "1.0.3",
|
|
||||||
"os-locale": "3.1.0",
|
|
||||||
"require-directory": "2.1.1",
|
|
||||||
"require-main-filename": "1.0.1",
|
|
||||||
"set-blocking": "2.0.0",
|
|
||||||
"string-width": "2.1.1",
|
|
||||||
"which-module": "2.0.0",
|
|
||||||
"y18n": "4.0.0",
|
|
||||||
"yargs-parser": "11.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yargs-parser": {
|
|
||||||
"version": "11.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
|
|
||||||
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
|
|
||||||
"requires": {
|
|
||||||
"camelcase": "5.3.1",
|
|
||||||
"decamelize": "1.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
21
fuzzywuzzy/app/proguard-rules.pro
vendored
21
fuzzywuzzy/app/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.Applicable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for the different ratios
|
|
||||||
*/
|
|
||||||
interface Ratio : Applicable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the ratio between the two strings
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return Integer representing ratio of similarity
|
|
||||||
*/
|
|
||||||
override fun apply(s1: String, s2: String): Int
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies the ratio between the two strings
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param sp String processor to pre-process strings before calculating the ratio
|
|
||||||
* @return Integer representing ratio of similarity
|
|
||||||
*/
|
|
||||||
fun apply(s1: String, s2: String, sp: ToStringFunction<String>): Int
|
|
||||||
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms an item of type T to a String.
|
|
||||||
*
|
|
||||||
* @param <T> The type of the item to transform.
|
|
||||||
</T> */
|
|
||||||
interface ToStringFunction<T> {
|
|
||||||
/**
|
|
||||||
* Transforms the input item to a string.
|
|
||||||
*
|
|
||||||
* @param item The item to transform.
|
|
||||||
* @return A string to use for comparing the item.
|
|
||||||
*/
|
|
||||||
fun apply(item: T): String
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A default ToStringFunction that returns the input string;
|
|
||||||
* used by methods that use plain strings in [FuzzySearch].
|
|
||||||
*/
|
|
||||||
val NO_PROCESS: ToStringFunction<String> = object : ToStringFunction<String> {
|
|
||||||
override fun apply(item: String): String {
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ratio/algorithm that can be applied
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface Applicable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply the ratio/algorithm to the input strings
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The score of similarity
|
|
||||||
*/
|
|
||||||
fun apply(s1: String, s2: String): Int
|
|
||||||
|
|
||||||
}
|
|
@ -1,854 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditOp
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditType
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditType.DELETE
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditType.INSERT
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditType.KEEP
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.EditType.REPLACE
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.MatchingBlock
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.structs.OpCode
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a port of all the functions needed from python-levenshtein C implementation.
|
|
||||||
* The code was ported line by line but unfortunately it was mostly undocumented,
|
|
||||||
* so it is mostly non readable (eg. var names)
|
|
||||||
*/
|
|
||||||
object DiffUtils {
|
|
||||||
|
|
||||||
private fun getEditOps(s1: String, s2: String): Array<EditOp> {
|
|
||||||
return getEditOps(s1.length, s1, s2.length, s2)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun getEditOps(len1: Int, s1: String, len2: Int, s2: String): Array<EditOp> {
|
|
||||||
var len1Copy = len1
|
|
||||||
var len2Copy = len2
|
|
||||||
|
|
||||||
var len1o = 0
|
|
||||||
var i = 0
|
|
||||||
|
|
||||||
var p1 = 0
|
|
||||||
var p2 = 0
|
|
||||||
|
|
||||||
while (len1Copy > 0 && len2Copy > 0 && s1[p1] == s2[p2]) {
|
|
||||||
len1Copy--
|
|
||||||
len2Copy--
|
|
||||||
|
|
||||||
p1++
|
|
||||||
p2++
|
|
||||||
|
|
||||||
len1o++
|
|
||||||
}
|
|
||||||
|
|
||||||
val len2o: Int = len1o
|
|
||||||
|
|
||||||
/* strip common suffix */
|
|
||||||
while (len1Copy > 0 && len2Copy > 0 && s1[p1 + len1Copy - 1] == s2[p2 + len2Copy - 1]) {
|
|
||||||
len1Copy--
|
|
||||||
len2Copy--
|
|
||||||
}
|
|
||||||
|
|
||||||
len1Copy++
|
|
||||||
len2Copy++
|
|
||||||
|
|
||||||
val matrix: IntArray = IntArray(len2Copy * len1Copy)
|
|
||||||
|
|
||||||
while (i < len2Copy) {
|
|
||||||
matrix[i] = i
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
i = 1
|
|
||||||
while (i < len1Copy) {
|
|
||||||
matrix[len2Copy * i] = i
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
while (i < len1Copy) {
|
|
||||||
|
|
||||||
var ptrPrev = (i - 1) * len2Copy
|
|
||||||
var ptrC = i * len2Copy
|
|
||||||
val ptrEnd = ptrC + len2Copy - 1
|
|
||||||
|
|
||||||
val char1 = s1[p1 + i - 1]
|
|
||||||
var ptrChar2 = p2
|
|
||||||
|
|
||||||
var x = i
|
|
||||||
|
|
||||||
ptrC++
|
|
||||||
|
|
||||||
while (ptrC <= ptrEnd) {
|
|
||||||
|
|
||||||
var c3 = matrix[ptrPrev++] + if (char1 != s2[ptrChar2++]) 1 else 0
|
|
||||||
x++
|
|
||||||
|
|
||||||
if (x > c3) {
|
|
||||||
x = c3
|
|
||||||
}
|
|
||||||
|
|
||||||
c3 = matrix[ptrPrev] + 1
|
|
||||||
|
|
||||||
if (x > c3) {
|
|
||||||
x = c3
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix[ptrC++] = x
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return editOpsFromCostMatrix(len1Copy, s1, p1, len1o, len2Copy, s2, p2, len2o, matrix)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun editOpsFromCostMatrix(len1: Int, c1: String, p1: Int, o1: Int,
|
|
||||||
len2: Int, c2: String, p2: Int, o2: Int,
|
|
||||||
matrix: IntArray): Array<EditOp> {
|
|
||||||
|
|
||||||
var i: Int = len1 - 1
|
|
||||||
var j: Int = len2 - 1
|
|
||||||
var pos: Int = matrix[len1 * len2 - 1]
|
|
||||||
|
|
||||||
var ptr: Int = len1 * len2 - 1
|
|
||||||
|
|
||||||
var dir = 0
|
|
||||||
|
|
||||||
val ops: Array<EditOp?> = arrayOfNulls(pos)
|
|
||||||
|
|
||||||
while (i > 0 || j > 0) {
|
|
||||||
|
|
||||||
if (dir < 0 && j != 0 && matrix[ptr] == matrix[ptr - 1] + 1) {
|
|
||||||
|
|
||||||
val eop = EditOp()
|
|
||||||
|
|
||||||
pos--
|
|
||||||
ops[pos] = eop
|
|
||||||
eop.type = INSERT
|
|
||||||
eop.spos = i + o1
|
|
||||||
eop.dpos = --j + o2
|
|
||||||
ptr--
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir > 0 && i != 0 && matrix[ptr] == matrix[ptr - len2] + 1) {
|
|
||||||
|
|
||||||
val eop = EditOp()
|
|
||||||
|
|
||||||
pos--
|
|
||||||
ops[pos] = eop
|
|
||||||
eop.type = DELETE
|
|
||||||
eop.spos = --i + o1
|
|
||||||
eop.dpos = j + o2
|
|
||||||
ptr -= len2
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != 0 && j != 0 && matrix[ptr] == matrix[ptr - len2 - 1]
|
|
||||||
&& c1[p1 + i - 1] == c2[p2 + j - 1]) {
|
|
||||||
|
|
||||||
i--
|
|
||||||
j--
|
|
||||||
ptr -= len2 + 1
|
|
||||||
dir = 0
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != 0 && j != 0 && matrix[ptr] == matrix[ptr - len2 - 1] + 1) {
|
|
||||||
|
|
||||||
pos--
|
|
||||||
|
|
||||||
val eop = EditOp()
|
|
||||||
ops[pos] = eop
|
|
||||||
|
|
||||||
eop.type = REPLACE
|
|
||||||
eop.spos = --i + o1
|
|
||||||
eop.dpos = --j + o2
|
|
||||||
|
|
||||||
ptr -= len2 + 1
|
|
||||||
dir = 0
|
|
||||||
continue
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 0 && j != 0 && matrix[ptr] == matrix[ptr - 1] + 1) {
|
|
||||||
|
|
||||||
pos--
|
|
||||||
val eop = EditOp()
|
|
||||||
ops[pos] = eop
|
|
||||||
eop.type = INSERT
|
|
||||||
eop.spos = i + o1
|
|
||||||
eop.dpos = --j + o2
|
|
||||||
ptr--
|
|
||||||
dir = -1
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir == 0 && i != 0 && matrix[ptr] == matrix[ptr - len2] + 1) {
|
|
||||||
pos--
|
|
||||||
val eop = EditOp()
|
|
||||||
ops[pos] = eop
|
|
||||||
|
|
||||||
eop.type = DELETE
|
|
||||||
eop.spos = --i + o1
|
|
||||||
eop.dpos = j + o2
|
|
||||||
ptr -= len2
|
|
||||||
dir = 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return ops.requireNoNulls()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMatchingBlocks(s1: String, s2: String): Array<MatchingBlock> {
|
|
||||||
|
|
||||||
return getMatchingBlocks(s1.length, s2.length, getEditOps(s1, s2))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getMatchingBlocks(len1: Int, len2: Int, ops: Array<OpCode>): Array<MatchingBlock?> {
|
|
||||||
|
|
||||||
val n = ops.size
|
|
||||||
|
|
||||||
var noOfMB = 0
|
|
||||||
var o = 0
|
|
||||||
|
|
||||||
var i: Int = n
|
|
||||||
while (i-- != 0) {
|
|
||||||
|
|
||||||
if (ops[o].type === KEEP) {
|
|
||||||
|
|
||||||
noOfMB++
|
|
||||||
|
|
||||||
while (i != 0 && ops[o].type === KEEP) {
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
break
|
|
||||||
|
|
||||||
}
|
|
||||||
o++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val matchingBlocks = arrayOfNulls<MatchingBlock>(noOfMB + 1)
|
|
||||||
var mb = 0
|
|
||||||
o = 0
|
|
||||||
matchingBlocks[mb] = MatchingBlock()
|
|
||||||
|
|
||||||
i = n
|
|
||||||
while (i != 0) {
|
|
||||||
|
|
||||||
if (ops[o].type === KEEP) {
|
|
||||||
|
|
||||||
|
|
||||||
matchingBlocks[mb]!!.spos = ops[o].sbeg
|
|
||||||
matchingBlocks[mb]!!.dpos = ops[o].dbeg
|
|
||||||
|
|
||||||
while (i != 0 && ops[o].type === KEEP) {
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
matchingBlocks[mb]!!.length = len1 - matchingBlocks[mb]!!.spos
|
|
||||||
mb++
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
matchingBlocks[mb]!!.length = ops[o].sbeg - matchingBlocks[mb]!!.spos
|
|
||||||
mb++
|
|
||||||
matchingBlocks[mb] = MatchingBlock()
|
|
||||||
}
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(mb == noOfMB)
|
|
||||||
|
|
||||||
val finalBlock = MatchingBlock()
|
|
||||||
finalBlock.spos = len1
|
|
||||||
finalBlock.dpos = len2
|
|
||||||
finalBlock.length = 0
|
|
||||||
|
|
||||||
matchingBlocks[mb] = finalBlock
|
|
||||||
|
|
||||||
return matchingBlocks
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun getMatchingBlocks(len1: Int, len2: Int, ops: Array<EditOp>): Array<MatchingBlock> {
|
|
||||||
|
|
||||||
val n = ops.size
|
|
||||||
|
|
||||||
var numberOfMatchingBlocks = 0
|
|
||||||
var spos: Int
|
|
||||||
var dpos: Int
|
|
||||||
|
|
||||||
var o = 0
|
|
||||||
|
|
||||||
dpos = 0
|
|
||||||
spos = dpos
|
|
||||||
|
|
||||||
var type: EditType
|
|
||||||
|
|
||||||
var i: Int = n
|
|
||||||
while (i != 0) {
|
|
||||||
|
|
||||||
|
|
||||||
while (ops[o].type === KEEP && --i != 0) {
|
|
||||||
o++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
break
|
|
||||||
|
|
||||||
if (spos < ops[o].spos || dpos < ops[o].dpos) {
|
|
||||||
|
|
||||||
numberOfMatchingBlocks++
|
|
||||||
spos = ops[o].spos
|
|
||||||
dpos = ops[o].dpos
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type = ops[o].type!!
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
REPLACE -> do {
|
|
||||||
spos++
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
DELETE -> do {
|
|
||||||
spos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
INSERT -> do {
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spos < len1 || dpos < len2) {
|
|
||||||
numberOfMatchingBlocks++
|
|
||||||
}
|
|
||||||
|
|
||||||
val matchingBlocks = arrayOfNulls<MatchingBlock>(numberOfMatchingBlocks + 1)
|
|
||||||
|
|
||||||
o = 0
|
|
||||||
dpos = 0
|
|
||||||
spos = dpos
|
|
||||||
var mbIndex = 0
|
|
||||||
|
|
||||||
|
|
||||||
i = n
|
|
||||||
while (i != 0) {
|
|
||||||
|
|
||||||
while (ops[o].type === KEEP && --i != 0)
|
|
||||||
o++
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
break
|
|
||||||
|
|
||||||
if (spos < ops[o].spos || dpos < ops[o].dpos) {
|
|
||||||
val mb = MatchingBlock()
|
|
||||||
|
|
||||||
mb.spos = spos
|
|
||||||
mb.dpos = dpos
|
|
||||||
mb.length = ops[o].spos - spos
|
|
||||||
spos = ops[o].spos
|
|
||||||
dpos = ops[o].dpos
|
|
||||||
|
|
||||||
matchingBlocks[mbIndex++] = mb
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type = ops[o].type!!
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
REPLACE -> do {
|
|
||||||
spos++
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
DELETE -> do {
|
|
||||||
spos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
INSERT -> do {
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spos < len1 || dpos < len2) {
|
|
||||||
assert(len1 - spos == len2 - dpos)
|
|
||||||
|
|
||||||
val mb = MatchingBlock()
|
|
||||||
mb.spos = spos
|
|
||||||
mb.dpos = dpos
|
|
||||||
mb.length = len1 - spos
|
|
||||||
|
|
||||||
matchingBlocks[mbIndex++] = mb
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(numberOfMatchingBlocks == mbIndex)
|
|
||||||
|
|
||||||
val finalBlock = MatchingBlock()
|
|
||||||
finalBlock.spos = len1
|
|
||||||
finalBlock.dpos = len2
|
|
||||||
finalBlock.length = 0
|
|
||||||
|
|
||||||
matchingBlocks[mbIndex] = finalBlock
|
|
||||||
|
|
||||||
|
|
||||||
return matchingBlocks.filterNotNull().toTypedArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun editOpsToOpCodes(ops: Array<EditOp>, len1: Int, len2: Int): Array<OpCode?> {
|
|
||||||
|
|
||||||
val n = ops.size
|
|
||||||
var noOfBlocks = 0
|
|
||||||
var i: Int
|
|
||||||
var spos: Int
|
|
||||||
var dpos: Int
|
|
||||||
var o = 0
|
|
||||||
var type: EditType
|
|
||||||
|
|
||||||
dpos = 0
|
|
||||||
spos = dpos
|
|
||||||
|
|
||||||
i = n
|
|
||||||
while (i != 0) {
|
|
||||||
|
|
||||||
while (ops[o].type === KEEP && --i != 0) {
|
|
||||||
o++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
break
|
|
||||||
|
|
||||||
if (spos < ops[o].spos || dpos < ops[o].dpos) {
|
|
||||||
|
|
||||||
noOfBlocks++
|
|
||||||
spos = ops[o].spos
|
|
||||||
dpos = ops[o].dpos
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Is this right?
|
|
||||||
noOfBlocks++
|
|
||||||
type = ops[o].type!!
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
REPLACE -> do {
|
|
||||||
spos++
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
DELETE -> do {
|
|
||||||
spos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
INSERT -> do {
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spos < len1 || dpos < len2)
|
|
||||||
noOfBlocks++
|
|
||||||
|
|
||||||
val opCodes = arrayOfNulls<OpCode>(noOfBlocks)
|
|
||||||
|
|
||||||
o = 0
|
|
||||||
dpos = 0
|
|
||||||
spos = dpos
|
|
||||||
var oIndex = 0
|
|
||||||
|
|
||||||
i = n
|
|
||||||
while (i != 0) {
|
|
||||||
|
|
||||||
while (ops[o].type === KEEP && --i != 0)
|
|
||||||
o++
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
break
|
|
||||||
|
|
||||||
val oc = OpCode()
|
|
||||||
opCodes[oIndex] = oc
|
|
||||||
oc.sbeg = spos
|
|
||||||
oc.dbeg = dpos
|
|
||||||
|
|
||||||
if (spos < ops[o].spos || dpos < ops[o].dpos) {
|
|
||||||
|
|
||||||
oc.type = KEEP
|
|
||||||
oc.send = ops[o].spos
|
|
||||||
spos = oc.send
|
|
||||||
oc.dend = ops[o].dpos
|
|
||||||
dpos = oc.dend
|
|
||||||
|
|
||||||
oIndex++
|
|
||||||
val oc2 = OpCode()
|
|
||||||
opCodes[oIndex] = oc2
|
|
||||||
oc2.sbeg = spos
|
|
||||||
oc2.dbeg = dpos
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
type = ops[o].type!!
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
REPLACE -> do {
|
|
||||||
spos++
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
DELETE -> do {
|
|
||||||
spos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
INSERT -> do {
|
|
||||||
dpos++
|
|
||||||
i--
|
|
||||||
o++
|
|
||||||
} while (i != 0 && ops[o].type === type &&
|
|
||||||
spos == ops[o].spos && dpos == ops[o].dpos)
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
opCodes[oIndex]!!.type = type
|
|
||||||
opCodes[oIndex]!!.send = spos
|
|
||||||
opCodes[oIndex]!!.dend = dpos
|
|
||||||
oIndex++
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spos < len1 || dpos < len2) {
|
|
||||||
|
|
||||||
assert(len1 - spos == len2 - dpos)
|
|
||||||
if (opCodes[oIndex] == null)
|
|
||||||
opCodes[oIndex] = OpCode()
|
|
||||||
opCodes[oIndex]!!.type = KEEP
|
|
||||||
opCodes[oIndex]!!.sbeg = spos
|
|
||||||
opCodes[oIndex]!!.dbeg = dpos
|
|
||||||
opCodes[oIndex]!!.send = len1
|
|
||||||
opCodes[oIndex]!!.dend = len2
|
|
||||||
|
|
||||||
oIndex++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(oIndex == noOfBlocks)
|
|
||||||
|
|
||||||
return opCodes
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun levEditDistance(s1: String, s2: String, xcost: Int): Int {
|
|
||||||
|
|
||||||
var i: Int
|
|
||||||
val half: Int
|
|
||||||
|
|
||||||
var c1 = s1
|
|
||||||
var c2 = s2
|
|
||||||
|
|
||||||
var str1 = 0
|
|
||||||
var str2 = 0
|
|
||||||
|
|
||||||
var len1 = s1.length
|
|
||||||
var len2 = s2.length
|
|
||||||
|
|
||||||
/* strip common prefix */
|
|
||||||
while (len1 > 0 && len2 > 0 && c1[str1] == c2[str2]) {
|
|
||||||
|
|
||||||
len1--
|
|
||||||
len2--
|
|
||||||
str1++
|
|
||||||
str2++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* strip common suffix */
|
|
||||||
while (len1 > 0 && len2 > 0 && c1[str1 + len1 - 1] == c2[str2 + len2 - 1]) {
|
|
||||||
len1--
|
|
||||||
len2--
|
|
||||||
}
|
|
||||||
|
|
||||||
/* catch trivial cases */
|
|
||||||
if (len1 == 0)
|
|
||||||
return len2
|
|
||||||
if (len2 == 0)
|
|
||||||
return len1
|
|
||||||
|
|
||||||
/* make the inner cycle (i.e. str2) the longer one */
|
|
||||||
if (len1 > len2) {
|
|
||||||
|
|
||||||
val nx = len1
|
|
||||||
val temp = str1
|
|
||||||
|
|
||||||
len1 = len2
|
|
||||||
len2 = nx
|
|
||||||
|
|
||||||
str1 = str2
|
|
||||||
str2 = temp
|
|
||||||
|
|
||||||
val t = c2
|
|
||||||
c2 = c1
|
|
||||||
c1 = t
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check len1 == 1 separately */
|
|
||||||
if (len1 == 1) {
|
|
||||||
return if (xcost != 0) {
|
|
||||||
len2 + 1 - 2 * memchr(c2, str2, c1[str1], len2)
|
|
||||||
} else {
|
|
||||||
len2 - memchr(c2, str2, c1[str1], len2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len1++
|
|
||||||
len2++
|
|
||||||
half = len1 shr 1
|
|
||||||
|
|
||||||
val row = IntArray(len2)
|
|
||||||
var end = len2 - 1
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
while (i < len2 - if (xcost != 0) 0 else half) {
|
|
||||||
row[i] = i
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* go through the matrix and compute the costs. yes, this is an extremely
|
|
||||||
* obfuscated version, but also extremely memory-conservative and relatively
|
|
||||||
* fast. */
|
|
||||||
|
|
||||||
if (xcost != 0) {
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
while (i < len1) {
|
|
||||||
|
|
||||||
var p = 1
|
|
||||||
|
|
||||||
val ch1 = c1[str1 + i - 1]
|
|
||||||
var c2p = str2
|
|
||||||
|
|
||||||
var D = i
|
|
||||||
var x = i
|
|
||||||
|
|
||||||
while (p <= end) {
|
|
||||||
|
|
||||||
if (ch1 == c2[c2p++]) {
|
|
||||||
x = --D
|
|
||||||
} else {
|
|
||||||
x++
|
|
||||||
}
|
|
||||||
D = row[p]
|
|
||||||
D++
|
|
||||||
|
|
||||||
if (x > D)
|
|
||||||
x = D
|
|
||||||
row[p++] = x
|
|
||||||
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* in this case we don't have to scan two corner triangles (of size len1/2)
|
|
||||||
* in the matrix because no best path can go throught them. note this
|
|
||||||
* breaks when len1 == len2 == 2 so the memchr() special case above is
|
|
||||||
* necessary */
|
|
||||||
|
|
||||||
row[0] = len1 - half - 1
|
|
||||||
i = 1
|
|
||||||
while (i < len1) {
|
|
||||||
var p: Int
|
|
||||||
|
|
||||||
val ch1 = c1[str1 + i - 1]
|
|
||||||
var c2p: Int
|
|
||||||
|
|
||||||
var D: Int
|
|
||||||
var x: Int
|
|
||||||
|
|
||||||
/* skip the upper triangle */
|
|
||||||
if (i >= len1 - half) {
|
|
||||||
val offset = i - (len1 - half)
|
|
||||||
val c3: Int
|
|
||||||
|
|
||||||
c2p = str2 + offset
|
|
||||||
p = offset
|
|
||||||
c3 = row[p++] + if (ch1 != c2[c2p++]) 1 else 0
|
|
||||||
x = row[p]
|
|
||||||
x++
|
|
||||||
D = x
|
|
||||||
if (x > c3) {
|
|
||||||
x = c3
|
|
||||||
}
|
|
||||||
row[p++] = x
|
|
||||||
} else {
|
|
||||||
p = 1
|
|
||||||
c2p = str2
|
|
||||||
x = i
|
|
||||||
D = x
|
|
||||||
}
|
|
||||||
/* skip the lower triangle */
|
|
||||||
if (i <= half + 1)
|
|
||||||
end = len2 + i - half - 2
|
|
||||||
/* main */
|
|
||||||
while (p <= end) {
|
|
||||||
val c3 = --D + if (ch1 != c2[c2p++]) 1 else 0
|
|
||||||
x++
|
|
||||||
if (x > c3) {
|
|
||||||
x = c3
|
|
||||||
}
|
|
||||||
D = row[p]
|
|
||||||
D++
|
|
||||||
if (x > D)
|
|
||||||
x = D
|
|
||||||
row[p++] = x
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* lower triangle sentinel */
|
|
||||||
if (i <= half) {
|
|
||||||
val c3 = --D + if (ch1 != c2[c2p]) 1 else 0
|
|
||||||
x++
|
|
||||||
if (x > c3) {
|
|
||||||
x = c3
|
|
||||||
}
|
|
||||||
row[p] = x
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i = row[end]
|
|
||||||
|
|
||||||
return i
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun memchr(haystack: String, offset: Int, needle: Char, num: Int): Int {
|
|
||||||
var numCopy = num
|
|
||||||
|
|
||||||
if (numCopy != 0) {
|
|
||||||
var p = 0
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
if (haystack[offset + p] == needle)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
p++
|
|
||||||
|
|
||||||
} while (--numCopy != 0)
|
|
||||||
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun getRatio(s1: String, s2: String): Double {
|
|
||||||
|
|
||||||
val len1 = s1.length
|
|
||||||
val len2 = s2.length
|
|
||||||
val lensum = len1 + len2
|
|
||||||
|
|
||||||
val editDistance = levEditDistance(s1, s2, 1)
|
|
||||||
|
|
||||||
return (lensum - editDistance) / lensum.toDouble()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun assert(assertion: Boolean) {
|
|
||||||
if (!assertion)
|
|
||||||
throw AssertionError()
|
|
||||||
}
|
|
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.Utils
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.model.BoundExtractedResult
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.model.ExtractedResult
|
|
||||||
|
|
||||||
|
|
||||||
class Extractor(private var cutoff: Int = 0) {
|
|
||||||
|
|
||||||
fun with(cutoff: Int): Extractor {
|
|
||||||
this.cutoff = cutoff
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of choices with their associated scores of similarity in a list
|
|
||||||
* of [ExtractedResult]
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices The list of choices
|
|
||||||
* @param func The function to apply
|
|
||||||
* @return The list of results
|
|
||||||
*/
|
|
||||||
fun extractWithoutOrder(query: String, choices: Collection<String>,
|
|
||||||
func: Applicable): List<ExtractedResult> {
|
|
||||||
val yields = ArrayList<ExtractedResult>()
|
|
||||||
|
|
||||||
for ((index, s) in choices.withIndex()) {
|
|
||||||
|
|
||||||
val score = func.apply(query, s)
|
|
||||||
|
|
||||||
if (score >= cutoff) {
|
|
||||||
yields.add(ExtractedResult(s, score, index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return yields
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the list of choices with their associated scores of similarity in a list
|
|
||||||
* of [ExtractedResult]
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices The list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The function to apply
|
|
||||||
* @return The list of results
|
|
||||||
*/
|
|
||||||
fun <T> extractWithoutOrder(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val yields = ArrayList<BoundExtractedResult<T>>()
|
|
||||||
|
|
||||||
for ((index, t) in choices.withIndex()) {
|
|
||||||
|
|
||||||
val s = toStringFunction.apply(t)
|
|
||||||
val score = func.apply(query, s)
|
|
||||||
|
|
||||||
if (score >= cutoff) {
|
|
||||||
yields.add(BoundExtractedResult(t, s, score, index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return yields
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func Scoring function
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun extractOne(query: String, choices: Collection<String>, func: Applicable): ExtractedResult {
|
|
||||||
val extracted = extractWithoutOrder(query, choices, func)
|
|
||||||
|
|
||||||
return extracted.maxOrNull()!!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func Scoring function
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun <T> extractOne(query: String, choices: Collection<T>, toStringFunction: ToStringFunction<T>,
|
|
||||||
func: Applicable): BoundExtractedResult<T> {
|
|
||||||
|
|
||||||
val extracted = extractWithoutOrder(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
return extracted.maxOrNull()!!
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>, func: Applicable): List<ExtractedResult> {
|
|
||||||
val best = extractWithoutOrder(query, choices, func)
|
|
||||||
|
|
||||||
return best.sortedDescending()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val best = extractWithoutOrder(query, choices, toStringFunction, func)
|
|
||||||
return best.sortedDescending()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param limit Limits the number of results and speeds up
|
|
||||||
* the search (k-top heap sort) is used
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>, func: Applicable, limit: Int): List<ExtractedResult> {
|
|
||||||
val best = extractWithoutOrder(query, choices, func)
|
|
||||||
|
|
||||||
val results = Utils.findTopKHeap(best, limit)
|
|
||||||
|
|
||||||
return results.sortedDescending()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param limit Limits the number of results and speeds up
|
|
||||||
* the search (k-top heap sort) is used
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable, limit: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val best = extractWithoutOrder(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
val results = Utils.findTopKHeap(best, limit)
|
|
||||||
return results.sortedDescending()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,771 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.TokenSet
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.TokenSort
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.WeightedRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.model.BoundExtractedResult
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.model.ExtractedResult
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.ratio.PartialRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.ratio.SimpleRatio
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FuzzySearch facade class
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
object FuzzySearch {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a Levenshtein simple ratio between the strings.
|
|
||||||
* This is indicates a measure of similarity
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The simple ratio
|
|
||||||
*/
|
|
||||||
fun ratio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return SimpleRatio().apply(s1, s2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a Levenshtein simple ratio between the strings.
|
|
||||||
* This is indicates a measure of similarity
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The simple ratio
|
|
||||||
*/
|
|
||||||
fun ratio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return SimpleRatio().apply(s1, s2, stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inconsistent substrings lead to problems in matching. This ratio
|
|
||||||
* uses a heuristic called "best partial" for when two strings
|
|
||||||
* are of noticeably different lengths.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The partial ratio
|
|
||||||
*/
|
|
||||||
fun partialRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return PartialRatio().apply(s1, s2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inconsistent substrings lead to problems in matching. This ratio
|
|
||||||
* uses a heuristic called "best partial" for when two strings
|
|
||||||
* are of noticeably different lengths.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The partial ratio
|
|
||||||
*/
|
|
||||||
fun partialRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return PartialRatio().apply(s1, s2, stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all alphanumeric tokens in the string and sort
|
|
||||||
* those tokens and then take ratio of resulting
|
|
||||||
* joined strings.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The partial ratio of the strings
|
|
||||||
*/
|
|
||||||
fun tokenSortPartialRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return TokenSort().apply(s1, s2, PartialRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all alphanumeric tokens in the string and sort
|
|
||||||
* those tokens and then take ratio of resulting
|
|
||||||
* joined strings.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The partial ratio of the strings
|
|
||||||
*/
|
|
||||||
fun tokenSortPartialRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return TokenSort().apply(s1, s2, PartialRatio(), stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all alphanumeric tokens in the string and sort
|
|
||||||
* those tokens and then take ratio of resulting
|
|
||||||
* joined strings.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The full ratio of the strings
|
|
||||||
*/
|
|
||||||
fun tokenSortRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return TokenSort().apply(s1, s2, SimpleRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find all alphanumeric tokens in the string and sort
|
|
||||||
* those tokens and then take ratio of resulting
|
|
||||||
* joined strings.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The full ratio of the strings
|
|
||||||
*/
|
|
||||||
fun tokenSortRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return TokenSort().apply(s1, s2, SimpleRatio(), stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the strings into tokens and computes intersections and remainders
|
|
||||||
* between the tokens of the two strings. A comparison string is then
|
|
||||||
* built up and is compared using the simple ratio algorithm.
|
|
||||||
* Useful for strings where words appear redundantly.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun tokenSetRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return TokenSet().apply(s1, s2, SimpleRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the strings into tokens and computes intersections and remainders
|
|
||||||
* between the tokens of the two strings. A comparison string is then
|
|
||||||
* built up and is compared using the simple ratio algorithm.
|
|
||||||
* Useful for strings where words appear redundantly.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun tokenSetRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return TokenSet().apply(s1, s2, SimpleRatio(), stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the strings into tokens and computes intersections and remainders
|
|
||||||
* between the tokens of the two strings. A comparison string is then
|
|
||||||
* built up and is compared using the simple ratio algorithm.
|
|
||||||
* Useful for strings where words appear redundantly.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun tokenSetPartialRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return TokenSet().apply(s1, s2, PartialRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits the strings into tokens and computes intersections and remainders
|
|
||||||
* between the tokens of the two strings. A comparison string is then
|
|
||||||
* built up and is compared using the simple ratio algorithm.
|
|
||||||
* Useful for strings where words appear redundantly.
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun tokenSetPartialRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return TokenSet().apply(s1, s2, PartialRatio(), stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a weighted ratio between the different algorithms for best results
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun weightedRatio(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return WeightedRatio().apply(s1, s2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates a weighted ratio between the different algorithms for best results
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @param stringFunction Functor which transforms strings before
|
|
||||||
* calculating the ratio
|
|
||||||
* @return The ratio of similarity
|
|
||||||
*/
|
|
||||||
fun weightedRatio(s1: String, s2: String, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
return WeightedRatio().apply(s1, s2, stringFunction)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>,
|
|
||||||
func: Applicable, limit: Int, cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
return extractor.extractTop(query, choices, func, limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param limit Limits the number of results and speeds up
|
|
||||||
* the search (k-top heap sort) is used
|
|
||||||
* @param cutoff Rejects any entries with score below this
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>,
|
|
||||||
limit: Int, cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
return extractor.extractTop(query, choices, WeightedRatio(), limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param limit The number of results to return
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>,
|
|
||||||
func: Applicable, limit: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, func, limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param limit The number of results to return
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractTop(query: String, choices: Collection<String>,
|
|
||||||
limit: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, WeightedRatio(), limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractSorted(query: String, choices: Collection<String>, func: Applicable): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractSorted(query: String, choices: Collection<String>, func: Applicable,
|
|
||||||
cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractSorted(query: String, choices: Collection<String>): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractSorted(query: String, choices: Collection<String>,
|
|
||||||
cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractAll(query: String, choices: Collection<String>, func: Applicable): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractAll(query: String, choices: Collection<String>, func: Applicable,
|
|
||||||
cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractAll(query: String, choices: Collection<String>): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun extractAll(query: String, choices: Collection<String>, cutoff: Int): List<ExtractedResult> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param func Scoring function
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun extractOne(query: String, choices: Collection<String>, func: Applicable): ExtractedResult {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractOne(query, choices, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun extractOne(query: String, choices: Collection<String>): ExtractedResult {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractOne(query, choices, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable,
|
|
||||||
limit: Int, cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, func, limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param limit Limits the number of results and speeds up
|
|
||||||
* the search (k-top heap sort) is used
|
|
||||||
* @param cutoff Rejects any entries with score below this
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, limit: Int, cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, WeightedRatio(), limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param limit The number of results to return
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable,
|
|
||||||
limit: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, func, limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain the
|
|
||||||
* top @param limit most similar choices
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param limit The number of results to return
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractTop(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, limit: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, WeightedRatio(), limit)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractSorted(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractSorted(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable,
|
|
||||||
cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractSorted(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a **sorted** list of [ExtractedResult] which contain all the choices
|
|
||||||
* with their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractSorted(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractTop(query, choices, toStringFunction, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractAll(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func The scoring function
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractAll(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable,
|
|
||||||
cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractAll(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, toStringFunction, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a list of [ExtractedResult] which contain all the choices with
|
|
||||||
* their corresponding score where higher is more similar
|
|
||||||
*
|
|
||||||
* @param query The query string
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param cutoff Keep only scores above cutoff
|
|
||||||
* @return A list of the results
|
|
||||||
*/
|
|
||||||
fun <T> extractAll(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, cutoff: Int): List<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
val extractor = Extractor(cutoff)
|
|
||||||
|
|
||||||
return extractor.extractWithoutOrder(query, choices, toStringFunction, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @param func Scoring function
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun <T> extractOne(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>, func: Applicable): BoundExtractedResult<T> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractOne(query, choices, toStringFunction, func)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the single best match above a score in a list of choices.
|
|
||||||
*
|
|
||||||
* @param query A string to match against
|
|
||||||
* @param choices A list of choices
|
|
||||||
* @param toStringFunction The ToStringFunction to be applied to all choices.
|
|
||||||
* @return An object containing the best match and it's score
|
|
||||||
*/
|
|
||||||
fun <T> extractOne(query: String, choices: Collection<T>,
|
|
||||||
toStringFunction: ToStringFunction<T>): BoundExtractedResult<T> {
|
|
||||||
|
|
||||||
val extractor = Extractor()
|
|
||||||
|
|
||||||
return extractor.extractOne(query, choices, toStringFunction, WeightedRatio())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("UNCHECKED_CAST")
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2017 Kotlin Algorithm Club
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
import kotlin.Comparator
|
|
||||||
|
|
||||||
class PriorityQueue<T>(size: Int, private val comparator: Comparator<T?>? = null) : Collection<T> {
|
|
||||||
override var size: Int = 0
|
|
||||||
private set
|
|
||||||
private var arr: Array<T?> = Array<Comparable<T>?>(size) { null } as Array<T?>
|
|
||||||
|
|
||||||
fun add(element: T) {
|
|
||||||
if (size + 1 == arr.size) {
|
|
||||||
resize()
|
|
||||||
}
|
|
||||||
arr[++size] = element
|
|
||||||
swim(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun peek(): T {
|
|
||||||
if (size == 0) throw NoSuchElementException()
|
|
||||||
return arr[1]!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun poll(): T {
|
|
||||||
if (size == 0) throw NoSuchElementException()
|
|
||||||
val res = peek()
|
|
||||||
arr.swap(1, size--)
|
|
||||||
sink(1)
|
|
||||||
arr[size + 1] = null
|
|
||||||
if ((size > 0) && (size == (arr.size - 1) / 4)) {
|
|
||||||
resize()
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun swim(n: Int) {
|
|
||||||
Companion.swim(arr, n, comparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sink(n: Int) {
|
|
||||||
Companion.sink(arr, n, size, comparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resize() {
|
|
||||||
val old = arr
|
|
||||||
// arr = Array<Comparable<T>?>(size * 2, { null }) as Array<T?>
|
|
||||||
arr = old.copyOf(old.size + 1)
|
|
||||||
// System.arraycopy(old, 0, arr, 0, size + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun isEmpty(): Boolean {
|
|
||||||
return size == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun contains(element: T): Boolean {
|
|
||||||
for (obj in this) {
|
|
||||||
if (obj == element) return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun containsAll(elements: Collection<T>): Boolean {
|
|
||||||
for (element in elements) {
|
|
||||||
if (!contains(element)) return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun iterator(): Iterator<T> {
|
|
||||||
return arr.copyOfRange(1, size + 1).map { it!! }.iterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private fun<T> greater(arr: Array<T>, i: Int, j: Int, comparator: Comparator<T>? = null): Boolean {
|
|
||||||
return if (comparator != null) {
|
|
||||||
comparator.compare(arr[i], arr[j]) > 0
|
|
||||||
} else {
|
|
||||||
val left = arr[i]!! as Comparable<T>
|
|
||||||
left > arr[j]!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun<T> sink(arr: Array<T>, a: Int, size: Int, comparator: Comparator<T>? = null ) {
|
|
||||||
var k = a
|
|
||||||
while (2 * k <= size) {
|
|
||||||
var j = 2 * k
|
|
||||||
if (j < size && greater(arr, j, j + 1, comparator)) j++
|
|
||||||
if (!greater(arr, k, j, comparator)) break
|
|
||||||
arr.swap(k, j)
|
|
||||||
k = j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun<T> swim(arr: Array<T?>, size: Int, comparator: Comparator<T?>? = null) {
|
|
||||||
var n = size
|
|
||||||
while (n > 1 && greater(arr, n / 2, n, comparator)) {
|
|
||||||
arr.swap(n, n / 2)
|
|
||||||
n /= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Array<T>.swap(i: Int, j: Int) {
|
|
||||||
val tmp = this[i]
|
|
||||||
this[i] = this[j]
|
|
||||||
this[j] = tmp
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.Applicable
|
|
||||||
|
|
||||||
abstract class BasicAlgorithm : Applicable {
|
|
||||||
|
|
||||||
var stringFunction: ToStringFunction<String>? = null
|
|
||||||
internal set
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.stringFunction = DefaultStringFunction()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(stringFunction: ToStringFunction<String>) {
|
|
||||||
this.stringFunction = stringFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun apply(s1: String, s2: String, stringProcessor: ToStringFunction<String>): Int
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return apply(s1, s2, this.stringFunction!!)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun with(stringFunction: ToStringFunction<String>): BasicAlgorithm {
|
|
||||||
this.stringFunction = stringFunction
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun noProcessor(): BasicAlgorithm {
|
|
||||||
this.stringFunction = ToStringFunction.NO_PROCESS
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
|
|
||||||
expect val pattern: String
|
|
||||||
|
|
||||||
class DefaultStringFunction : ToStringFunction<String> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the default string processing on the item string
|
|
||||||
*
|
|
||||||
* @param `item` Input string
|
|
||||||
* @return The processed string
|
|
||||||
*/
|
|
||||||
override fun apply(item: String) = subNonAlphaNumeric(item, " ").toLowerCase().trim { it <= ' ' }
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
private const val nonUnicodePattern = "[^\\p{Alnum}]"
|
|
||||||
private val r by lazy {
|
|
||||||
try {
|
|
||||||
Regex(pattern)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
// Even though Android supports the unicode pattern class
|
|
||||||
// for some reason it throws an IllegalArgumentException
|
|
||||||
// if we pass the flag like on standard Java runtime
|
|
||||||
//
|
|
||||||
// We catch this and recompile without the flag (unicode should still work)
|
|
||||||
Regex(nonUnicodePattern)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Substitute non alphanumeric characters.
|
|
||||||
*
|
|
||||||
* @param in The input string
|
|
||||||
* @param sub The string to substitute with
|
|
||||||
* @return The replaced string
|
|
||||||
*/
|
|
||||||
fun subNonAlphaNumeric(`in`: String, sub: String): String {
|
|
||||||
val m = r.find(`in`)
|
|
||||||
return if (m != null) {
|
|
||||||
r.replace(`in`, sub)
|
|
||||||
} else {
|
|
||||||
`in`
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
internal object PrimitiveUtils {
|
|
||||||
|
|
||||||
fun max(vararg elems: Double): Double {
|
|
||||||
|
|
||||||
if (elems.isEmpty()) return 0.0
|
|
||||||
|
|
||||||
var best = elems[0]
|
|
||||||
|
|
||||||
for (t in elems) {
|
|
||||||
if (t > best) {
|
|
||||||
best = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return best
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun max(vararg elems: Int): Int {
|
|
||||||
|
|
||||||
if (elems.size == 0) return 0
|
|
||||||
|
|
||||||
var best = elems[0]
|
|
||||||
|
|
||||||
for (t in elems) {
|
|
||||||
if (t > best) {
|
|
||||||
best = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return best
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.Ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.ratio.SimpleRatio
|
|
||||||
|
|
||||||
abstract class RatioAlgorithm : BasicAlgorithm {
|
|
||||||
|
|
||||||
var ratio: Ratio? = null
|
|
||||||
|
|
||||||
constructor() : super() {
|
|
||||||
this.ratio = SimpleRatio()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(stringFunction: ToStringFunction<String>) : super(stringFunction) {}
|
|
||||||
|
|
||||||
constructor(ratio: Ratio) : super() {
|
|
||||||
this.ratio = ratio
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
constructor(stringFunction: ToStringFunction<String>, ratio: Ratio) : super(stringFunction) {
|
|
||||||
this.ratio = ratio
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun apply(s1: String, s2: String, ratio: Ratio, stringFunction: ToStringFunction<String>): Int
|
|
||||||
|
|
||||||
fun with(ratio: Ratio): RatioAlgorithm {
|
|
||||||
this.ratio = ratio
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
fun apply(s1: String, s2: String, ratio: Ratio): Int {
|
|
||||||
return apply(s1, s2, ratio, stringFunction!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, stringProcessor: ToStringFunction<String>): Int {
|
|
||||||
return apply(s1, s2, ratio!!, stringProcessor)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
internal object SetUtils {
|
|
||||||
|
|
||||||
fun <T> intersection(s1: Set<T>, s2: Set<T>): Set<T> {
|
|
||||||
|
|
||||||
val intersection = HashSet(s1)
|
|
||||||
intersection.retainAll(s2)
|
|
||||||
|
|
||||||
return intersection
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> difference(s1: Set<T>, s2: Set<T>): Set<T> {
|
|
||||||
|
|
||||||
val difference = HashSet(s1)
|
|
||||||
difference.removeAll(s2)
|
|
||||||
|
|
||||||
return difference
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.Ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
|
|
||||||
class TokenSet : RatioAlgorithm() {
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, ratio: Ratio, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
var s1Copy = s1
|
|
||||||
var s2Copy = s2
|
|
||||||
|
|
||||||
s1Copy = stringFunction.apply(s1Copy)
|
|
||||||
s2Copy = stringFunction.apply(s2Copy)
|
|
||||||
|
|
||||||
val tokens1 = Utils.tokenizeSet(s1Copy)
|
|
||||||
val tokens2 = Utils.tokenizeSet(s2Copy)
|
|
||||||
|
|
||||||
val intersection = SetUtils.intersection(tokens1, tokens2)
|
|
||||||
val diff1to2 = SetUtils.difference(tokens1, tokens2)
|
|
||||||
val diff2to1 = SetUtils.difference(tokens2, tokens1)
|
|
||||||
|
|
||||||
val sortedInter = Utils.sortAndJoin(intersection, " ").trim()
|
|
||||||
val sorted1to2 = (sortedInter + " " + Utils.sortAndJoin(diff1to2, " ")).trim { it <= ' ' }
|
|
||||||
val sorted2to1 = (sortedInter + " " + Utils.sortAndJoin(diff2to1, " ")).trim { it <= ' ' }
|
|
||||||
|
|
||||||
val results = ArrayList<Int>()
|
|
||||||
|
|
||||||
results.add(ratio.apply(sortedInter, sorted1to2))
|
|
||||||
results.add(ratio.apply(sortedInter, sorted2to1))
|
|
||||||
results.add(ratio.apply(sorted1to2, sorted2to1))
|
|
||||||
|
|
||||||
return results.maxOrNull()!!
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.Ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
|
|
||||||
|
|
||||||
class TokenSort : RatioAlgorithm() {
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, ratio: Ratio, stringFunction: ToStringFunction<String>): Int {
|
|
||||||
|
|
||||||
val sorted1 = processAndSort(s1, stringFunction)
|
|
||||||
val sorted2 = processAndSort(s2, stringFunction)
|
|
||||||
|
|
||||||
return ratio.apply(sorted1, sorted2)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processAndSort(input: String, stringProcessor: ToStringFunction<String>): String {
|
|
||||||
var inputCopy = input
|
|
||||||
|
|
||||||
inputCopy = stringProcessor.apply(inputCopy)
|
|
||||||
val wordsArray = inputCopy.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
|
||||||
|
|
||||||
val words = listOf(*wordsArray)
|
|
||||||
val joined = Utils.sortAndJoin(words, " ")
|
|
||||||
|
|
||||||
return joined.trim { it <= ' ' }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.PriorityQueue
|
|
||||||
|
|
||||||
|
|
||||||
object Utils {
|
|
||||||
|
|
||||||
|
|
||||||
internal fun tokenize(`in`: String): List<String> {
|
|
||||||
|
|
||||||
return listOf(*`in`.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun tokenizeSet(`in`: String): Set<String> {
|
|
||||||
|
|
||||||
return HashSet(tokenize(`in`))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun sortAndJoin(col: List<String>, sep: String): String {
|
|
||||||
|
|
||||||
// Collections.sort(col)
|
|
||||||
|
|
||||||
return join(col.sorted(), sep)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun join(strings: List<String>, sep: String): String {
|
|
||||||
val buf = StringBuilder(strings.size * 16)
|
|
||||||
|
|
||||||
for (i in strings.indices) {
|
|
||||||
|
|
||||||
if (i < strings.size) {
|
|
||||||
buf.append(sep)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.append(strings[i])
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return buf.toString().trim { it <= ' ' }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun sortAndJoin(col: Set<String>, sep: String): String {
|
|
||||||
|
|
||||||
return sortAndJoin(ArrayList(col), sep)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Comparable<T>> findTopKHeap(arr: List<T>, k: Int): List<T> {
|
|
||||||
val pq = PriorityQueue<T>(arr.size)
|
|
||||||
|
|
||||||
for (x in arr) {
|
|
||||||
if (pq.size < k)
|
|
||||||
pq.add(x)
|
|
||||||
else if (x > pq.peek()) {
|
|
||||||
pq.poll()
|
|
||||||
pq.add(x)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val res = ArrayList<T>()
|
|
||||||
try {
|
|
||||||
for (i in k downTo 1) {
|
|
||||||
res.add(pq.poll())
|
|
||||||
}
|
|
||||||
} catch (e: NoSuchElementException) {
|
|
||||||
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun <T : Comparable<T>> max(vararg elems: T): T? {
|
|
||||||
|
|
||||||
if (elems.isEmpty()) return null
|
|
||||||
|
|
||||||
var best = elems[0]
|
|
||||||
|
|
||||||
for (t in elems) {
|
|
||||||
if (t.compareTo(best) > 0) {
|
|
||||||
best = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return best
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.partialRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.tokenSetPartialRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.tokenSetRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.tokenSortPartialRatio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch.tokenSortRatio
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
import kotlin.math.round
|
|
||||||
|
|
||||||
class WeightedRatio : BasicAlgorithm() {
|
|
||||||
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, stringProcessor: ToStringFunction<String>): Int {
|
|
||||||
var s1Copy = s1
|
|
||||||
var s2Copy = s2
|
|
||||||
|
|
||||||
s1Copy = stringProcessor.apply(s1Copy)
|
|
||||||
s2Copy = stringProcessor.apply(s2Copy)
|
|
||||||
|
|
||||||
val len1 = s1Copy.length
|
|
||||||
val len2 = s2Copy.length
|
|
||||||
|
|
||||||
if (len1 == 0 || len2 == 0) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var tryPartials = TRY_PARTIALS
|
|
||||||
val unbaseScale = UNBASE_SCALE
|
|
||||||
var partialScale = PARTIAL_SCALE
|
|
||||||
|
|
||||||
val base = ratio(s1Copy, s2Copy)
|
|
||||||
val lenRatio = max(len1, len2).toDouble() / min(len1, len2)
|
|
||||||
|
|
||||||
// if strings are similar length don't use partials
|
|
||||||
if (lenRatio < 1.5) tryPartials = false
|
|
||||||
|
|
||||||
// if one string is much shorter than the other
|
|
||||||
if (lenRatio > 8) partialScale = .6
|
|
||||||
|
|
||||||
if (tryPartials) {
|
|
||||||
|
|
||||||
val partial = partialRatio(s1Copy, s2Copy) * partialScale
|
|
||||||
val partialSor = tokenSortPartialRatio(s1Copy, s2Copy) * unbaseScale * partialScale
|
|
||||||
val partialSet = tokenSetPartialRatio(s1Copy, s2Copy) * unbaseScale * partialScale
|
|
||||||
|
|
||||||
return round(max(max(max(base.toDouble(), partial), partialSor), partialSet)).toInt()
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
val tokenSort = tokenSortRatio(s1Copy, s2Copy) * unbaseScale
|
|
||||||
val tokenSet = tokenSetRatio(s1Copy, s2Copy) * unbaseScale
|
|
||||||
|
|
||||||
return round(max(max(base.toDouble(), tokenSort), tokenSet)).toInt()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
const val UNBASE_SCALE = .95
|
|
||||||
const val PARTIAL_SCALE = .90
|
|
||||||
const val TRY_PARTIALS = true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.model
|
|
||||||
|
|
||||||
class BoundExtractedResult<T>(val referent: T, var string: String?, val score: Int, val index: Int) : Comparable<BoundExtractedResult<T>> {
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "(string: $string, score: $score, index: $index)"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun compareTo(other: BoundExtractedResult<T>): Int {
|
|
||||||
return this.score.compareTo(other.score)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.model
|
|
||||||
|
|
||||||
data class ExtractedResult(var string: String?, val score: Int, val index: Int) : Comparable<ExtractedResult> {
|
|
||||||
|
|
||||||
override fun compareTo(other: ExtractedResult): Int {
|
|
||||||
return this.score.compareTo(other.score)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "(string: $string, score: $score, index: $index)"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.ratio
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.Ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.DiffUtils
|
|
||||||
import kotlin.math.round
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Partial ratio of similarity
|
|
||||||
*/
|
|
||||||
class PartialRatio : Ratio {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a partial ratio between the strings
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The partial ratio
|
|
||||||
*/
|
|
||||||
override fun apply(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
val shorter: String
|
|
||||||
val longer: String
|
|
||||||
|
|
||||||
if (s1.length < s2.length) {
|
|
||||||
|
|
||||||
shorter = s1
|
|
||||||
longer = s2
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
shorter = s2
|
|
||||||
longer = s1
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val matchingBlocks = DiffUtils.getMatchingBlocks(shorter, longer)
|
|
||||||
|
|
||||||
val scores = ArrayList<Double>()
|
|
||||||
|
|
||||||
for (mb in matchingBlocks) {
|
|
||||||
|
|
||||||
val dist = mb.dpos - mb.spos
|
|
||||||
|
|
||||||
val longStart = if (dist > 0) dist else 0
|
|
||||||
var longEnd = longStart + shorter.length
|
|
||||||
|
|
||||||
if (longEnd > longer.length) longEnd = longer.length
|
|
||||||
|
|
||||||
val longSubstr = longer.substring(longStart, longEnd)
|
|
||||||
|
|
||||||
val ratio = DiffUtils.getRatio(shorter, longSubstr)
|
|
||||||
|
|
||||||
if (ratio > .995) {
|
|
||||||
return 100
|
|
||||||
} else {
|
|
||||||
scores.add(ratio)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return round(100 * scores.maxOrNull()!!).toInt()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, sp: ToStringFunction<String>): Int {
|
|
||||||
return apply(sp.apply(s1), sp.apply(s2))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.ratio
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.Ratio
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.ToStringFunction
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.DiffUtils
|
|
||||||
import kotlin.math.round
|
|
||||||
|
|
||||||
class SimpleRatio : Ratio {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Computes a simple Levenshtein distance ratio between the strings
|
|
||||||
*
|
|
||||||
* @param s1 Input string
|
|
||||||
* @param s2 Input string
|
|
||||||
* @return The resulting ratio of similarity
|
|
||||||
*/
|
|
||||||
override fun apply(s1: String, s2: String): Int {
|
|
||||||
|
|
||||||
return round(100 * DiffUtils.getRatio(s1, s2)).toInt()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(s1: String, s2: String, sp: ToStringFunction<String>): Int {
|
|
||||||
return apply(sp.apply(s1), sp.apply(s2))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.structs
|
|
||||||
|
|
||||||
data class EditOp(
|
|
||||||
|
|
||||||
var type: EditType? = null,
|
|
||||||
var spos: Int = 0, // source block pos
|
|
||||||
var dpos: Int = 0 // destination block pos
|
|
||||||
) {
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return type!!.name + "(" + spos + "," + dpos + ")"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MatchingBlock {
|
|
||||||
var spos: Int = 0
|
|
||||||
var dpos: Int = 0
|
|
||||||
var length: Int = 0
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "($spos,$dpos,$length)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class OpCode {
|
|
||||||
|
|
||||||
var type: EditType? = null
|
|
||||||
var sbeg: Int = 0
|
|
||||||
var send: Int = 0
|
|
||||||
var dbeg: Int = 0
|
|
||||||
var dend: Int = 0
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return (type!!.name + "(" + sbeg + "," + send + ","
|
|
||||||
+ dbeg + "," + dend + ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class EditType {
|
|
||||||
DELETE,
|
|
||||||
EQUAL,
|
|
||||||
INSERT,
|
|
||||||
REPLACE,
|
|
||||||
KEEP
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.algorithms
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
//actual val pattern: String ="[\\W_]+/g"
|
|
||||||
actual val pattern = """[^\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]"""
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
|
@ -1,4 +0,0 @@
|
|||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
//actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
|
||||||
actual val pattern: String = """/[\W]*/"""
|
|
@ -1,56 +0,0 @@
|
|||||||
package kotlin.com.willowtree.fuzzywuzzy
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.Extractor
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.WeightedRatio
|
|
||||||
import kotlin.test.BeforeTest
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class ExtractorTest {
|
|
||||||
|
|
||||||
lateinit var choices: List<String>
|
|
||||||
private lateinit var extractor: Extractor
|
|
||||||
|
|
||||||
@BeforeTest
|
|
||||||
fun setUp() {
|
|
||||||
choices = listOf("google", "bing", "facebook", "linkedin", "twitter", "googleplus", "bingnews", "plexoogl")
|
|
||||||
extractor = Extractor()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractWithoutOrder() {
|
|
||||||
|
|
||||||
val res = extractor.extractWithoutOrder("goolge", choices, WeightedRatio())
|
|
||||||
|
|
||||||
assertEquals(res.size, choices.size)
|
|
||||||
assertTrue(res[0].score > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractOne() {
|
|
||||||
|
|
||||||
val res = extractor.extractOne("goolge", choices, WeightedRatio())
|
|
||||||
|
|
||||||
assertEquals(res.string, "google")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractBests() {
|
|
||||||
|
|
||||||
val res = extractor.extractTop("goolge", choices, WeightedRatio())
|
|
||||||
|
|
||||||
assertTrue(res[0].string == "google" && res[1].string == "googleplus")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractBests1() {
|
|
||||||
|
|
||||||
val res = extractor.extractTop("goolge", choices, WeightedRatio(), 3)
|
|
||||||
|
|
||||||
assertEquals(res.size, 3)
|
|
||||||
assertTrue(res[0].string == "google" && res.get(1).string == "googleplus" && res.get(2).string == "plexoogl")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
package kotlin.com.willowtree.fuzzywuzzy
|
|
||||||
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.ratio.SimpleRatio
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
|
|
||||||
class FuzzyWuzzyTest {
|
|
||||||
|
|
||||||
|
|
||||||
val choices = listOf("google", "bing", "facebook", "linkedin", "twitter", "googleplus", "bingnews", "plexoogl")
|
|
||||||
val moreChoices = listOf("Atlanta Falcons", "New York Jets", "New York Giants", "Dallas Cowboys")
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testRatio() {
|
|
||||||
assertEquals(76, FuzzySearch.ratio("mysmilarstring", "mymostsimilarstsdsdring"))
|
|
||||||
assertEquals(72, FuzzySearch.ratio("mysmilarstring", "myawfullysimilarstirng"))
|
|
||||||
assertEquals(97, FuzzySearch.ratio("mysmilarstring", "mysimilarstring"))
|
|
||||||
assertEquals(75, FuzzySearch.ratio("csr", "c s r"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testPartialRatio() {
|
|
||||||
|
|
||||||
assertEquals(71, FuzzySearch.partialRatio("similar", "somewhresimlrbetweenthisstring"))
|
|
||||||
assertEquals(43, FuzzySearch.partialRatio("similar", "notinheresim"))
|
|
||||||
assertEquals(38, FuzzySearch.partialRatio("pros holdings, inc.", "settlement facility dow corning trust"))
|
|
||||||
assertEquals(33, FuzzySearch.partialRatio("Should be the same", "Opposite ways go alike"))
|
|
||||||
assertEquals(33, FuzzySearch.partialRatio("Opposite ways go alike", "Should be the same"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testTokenSortPartial() {
|
|
||||||
|
|
||||||
assertEquals(67, FuzzySearch.tokenSortPartialRatio("mvn", "wwwwww.mavencentral.comm"))
|
|
||||||
assertEquals(100, FuzzySearch.tokenSortPartialRatio(" order words out of ", " words out of order"))
|
|
||||||
assertEquals(44, FuzzySearch.tokenSortPartialRatio("Testing token set ratio token", "Added another test"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testTokenSortRatio() {
|
|
||||||
assertEquals(84, FuzzySearch.tokenSortRatio("fuzzy was a bear", "fuzzy fuzzy was a bear"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testTokenSetRatio() {
|
|
||||||
|
|
||||||
assertEquals(100, FuzzySearch.tokenSetRatio("fuzzy fuzzy fuzzy bear", "fuzzy was a bear"))
|
|
||||||
assertEquals(39, FuzzySearch.tokenSetRatio("Testing token set ratio token", "Added another test"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testTokenSetPartial() {
|
|
||||||
|
|
||||||
assertEquals(11, FuzzySearch.tokenSetPartialRatio("fuzzy was a bear", "blind 100"))
|
|
||||||
assertEquals(67, FuzzySearch.partialRatio("chicago transit authority", "cta"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testWeightedRatio() {
|
|
||||||
|
|
||||||
|
|
||||||
assertEquals(60, FuzzySearch.weightedRatio("mvn", "wwwwww.mavencentral.comm"))
|
|
||||||
assertEquals(40, FuzzySearch.weightedRatio("mvn", "www'l34.423.4/23.4/234//////www.mavencentral.comm"))
|
|
||||||
assertEquals(97, FuzzySearch.weightedRatio("The quick brown fox jimps ofver the small lazy dog",
|
|
||||||
"the quick brown fox jumps over the small lazy dog"))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractTop() {
|
|
||||||
|
|
||||||
val res = FuzzySearch.extractTop("goolge", choices, 2)
|
|
||||||
val res2 = FuzzySearch.extractTop("goolge", choices, SimpleRatio(), 2)
|
|
||||||
|
|
||||||
assertEquals(res.size, 2)
|
|
||||||
assertTrue(res.get(0).string == "google" && res.get(1).string == "googleplus")
|
|
||||||
|
|
||||||
assertEquals(res2.size, 2)
|
|
||||||
assertTrue(res2.get(0).string == "google" && res2.get(1).string == "googleplus")
|
|
||||||
|
|
||||||
assertTrue(FuzzySearch.extractTop("goolge", choices, 2, 100).isEmpty())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractAll() {
|
|
||||||
|
|
||||||
val res = FuzzySearch.extractAll("goolge", choices)
|
|
||||||
|
|
||||||
assertEquals(res.size, choices.size)
|
|
||||||
assertEquals(res.get(0).string, "google")
|
|
||||||
|
|
||||||
assertEquals(FuzzySearch.extractAll("goolge", choices, 40).size, 3)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractSorted() {
|
|
||||||
|
|
||||||
val res = FuzzySearch.extractSorted("goolge", choices)
|
|
||||||
|
|
||||||
assertEquals(res.size, choices.size)
|
|
||||||
assertEquals(res.get(0).string, "google")
|
|
||||||
assertEquals(res.get(1).string, "googleplus")
|
|
||||||
|
|
||||||
assertEquals(FuzzySearch.extractSorted("goolge", choices, 40).size, 3)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExtractOne() {
|
|
||||||
|
|
||||||
val res = FuzzySearch.extractOne("twiter", choices, SimpleRatio())
|
|
||||||
val res2 = FuzzySearch.extractOne("twiter", choices)
|
|
||||||
val res3 = FuzzySearch.extractOne("cowboys", moreChoices)
|
|
||||||
|
|
||||||
assertEquals(res.string, "twitter")
|
|
||||||
assertEquals(res2.string, "twitter")
|
|
||||||
assertTrue(res3.string == "Dallas Cowboys" && res3.score == 90)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
|||||||
package com.willowtreeapps.fuzzywuzzy.algorithms
|
|
||||||
|
|
||||||
import com.willowtreeapps.fuzzywuzzy.diffutils.algorithms.DefaultStringFunction
|
|
||||||
import kotlin.test.Ignore
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class DefaultStringProcessorTest {
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun testProcess() {
|
|
||||||
val inp = "s.trim μεγιουνικουντ n/o/n a.lph.a n.um"
|
|
||||||
|
|
||||||
assertEquals("s trim μεγιουνικουντ n o n a lph a n um", DefaultStringFunction().apply(inp))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
|
||||||
|
|
||||||
actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
|
@ -1,48 +0,0 @@
|
|||||||
buildscript {
|
|
||||||
apply from: "$rootDir/fuzzywuzzy/gradle/dependencies.gradle"
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
maven { url 'https://dl.bintray.com/jetbrains/kotlin-native-dependencies' }
|
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
|
||||||
jcenter()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
classpath deps.plugins.kotlin
|
|
||||||
classpath deps.plugins.dokka
|
|
||||||
classpath deps.plugins.node
|
|
||||||
}
|
|
||||||
}
|
|
||||||
apply from: "$rootDir/fuzzywuzzy/gradle/dependencies.gradle"
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
google()
|
|
||||||
jcenter()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
group = GROUP
|
|
||||||
version = VERSION_NAME
|
|
||||||
}
|
|
||||||
|
|
||||||
task clean(type: Delete) {
|
|
||||||
delete rootProject.buildDir
|
|
||||||
}
|
|
||||||
/*def addDependency(Upload task, String groupId, String artifactId, String version, String type) {
|
|
||||||
task.repositories.withType(org.gradle.api.artifacts.maven.MavenDeployer) { mavenDeployer ->
|
|
||||||
task.doFirst {
|
|
||||||
mavenDeployer.pom.whenConfigured {
|
|
||||||
// For whatever reason we can't 'new' these ourselves. Clone an existing instance instead.
|
|
||||||
def dependency = it.dependencies.get(0).clone()
|
|
||||||
dependency.groupId = groupId
|
|
||||||
dependency.artifactId = artifactId
|
|
||||||
dependency.version = version
|
|
||||||
dependency.type = type
|
|
||||||
it.dependencies.add(dependency)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
#
|
|
||||||
# * Copyright (c) 2021 Shabinder Singh
|
|
||||||
# * This program is free software: you can redistribute it and/or modify
|
|
||||||
# * it under the terms of the GNU General Public License as published by
|
|
||||||
# * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# * (at your option) any later version.
|
|
||||||
# *
|
|
||||||
# * This program is distributed in the hope that it will be useful,
|
|
||||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# * GNU General Public License for more details.
|
|
||||||
# *
|
|
||||||
# * You should have received a copy of the GNU General Public License
|
|
||||||
# * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Project-wide Gradle settings.
|
|
||||||
# IDE (e.g. Android Studio) users:
|
|
||||||
# Gradle settings configured through the IDE *will override*
|
|
||||||
# any settings specified in this file.
|
|
||||||
# For more details on how to configure your build environment visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
|
||||||
org.gradle.jvmargs=-Xmx1536m
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
|
||||||
# org.gradle.parallel=true
|
|
||||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
|
||||||
# Android operating system, and which are packaged with your app's APK
|
|
||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
|
||||||
android.useAndroidX=true
|
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
|
||||||
android.enableJetifier=true
|
|
||||||
# Kotlin code style for this project: "official" or "obsolete":
|
|
||||||
kotlin.code.style=official
|
|
||||||
|
|
||||||
GROUP=com.willowtreeapps.fuzzywuzzy-kotlin
|
|
||||||
VERSION_NAME=0.1.1
|
|
||||||
|
|
||||||
POM_ARTIFACT_ID=fuzzywuzzy
|
|
||||||
POM_DESCRIPTION=Fuzzy string matching for kotlin multiplatform
|
|
||||||
POM_NAME=fuzzywuzzy-kotlin
|
|
||||||
POM_URL=https://github.com/willowtreeapps/fuzzywuzzy-kotlin/
|
|
||||||
POM_SCM_URL=https://github.com/willowtreeapps/fuzzywuzzy-kotlin/
|
|
||||||
POM_SCM_CONNECTION=scm:git:git://github.com/willowtreeapps/fuzzywuzzy-kotlin.git
|
|
||||||
POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/willowtreeapps/fuzzywuzzy-kotlin.git
|
|
||||||
|
|
||||||
POM_LICENCE_NAME=The Apache Software License, Version 2.0
|
|
||||||
POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
|
|
||||||
POM_LICENCE_DIST=repo
|
|
||||||
|
|
||||||
POM_DEVELOPER_ID=willowtreeapps
|
|
||||||
POM_DEVELOPER_NAME=WillowTree, LLC.
|
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ext.versions = [
|
|
||||||
kotlin : '1.4.30',
|
|
||||||
kotlinCoroutines: '1.4.2',
|
|
||||||
dokka : '1.4.30',
|
|
||||||
nodePlugin: '1.3.1'
|
|
||||||
]
|
|
||||||
ext.deps = [
|
|
||||||
plugins: [
|
|
||||||
android: 'com.android.tools.build:gradle:4.0.2',
|
|
||||||
kotlin : "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}",
|
|
||||||
dokka : "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}",
|
|
||||||
node : "com.moowork.gradle:gradle-node-plugin:${versions.nodePlugin}"
|
|
||||||
]
|
|
||||||
]
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
def pomConfig = {
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name "The Apache Software License, Version 2.0"
|
|
||||||
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
|
|
||||||
distribution "repo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id "WillowTree"
|
|
||||||
name "WillowTree Team"
|
|
||||||
organization "WillowTree"
|
|
||||||
organizationUrl "http://www.willowtreeapps.com"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scm {
|
|
||||||
url "https://github.com/willowtreeapps/fuzzywuzzy-kotlin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.ext.configureMavenCentralMetadata = { pom ->
|
|
||||||
def root = asNode()
|
|
||||||
root.appendNode('name', project.name)
|
|
||||||
root.appendNode('description', 'FuzzyWuzzy-Kotlin is a port of the python fuzzy string matching library to Kotlin Multiplatform (JVM, Native, JS, Wasm)')
|
|
||||||
root.appendNode('url', 'https://github.com/willowtreeapps/fuzzywuzzy-kotlin')
|
|
||||||
root.children().last() + pomConfig
|
|
||||||
}
|
|
@ -1,153 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
apply plugin: 'maven'
|
|
||||||
apply plugin: 'maven-publish'
|
|
||||||
apply plugin: 'signing'
|
|
||||||
apply plugin: 'org.jetbrains.dokka'
|
|
||||||
|
|
||||||
|
|
||||||
dokka {
|
|
||||||
impliedPlatforms = ["Common"] // This will force platform tags for all non-common sources e.g. "JVM"
|
|
||||||
kotlinTasks {
|
|
||||||
// dokka fails to retrieve sources from MPP-tasks so they must be set empty to avoid exception
|
|
||||||
// use sourceRoot instead (see below)
|
|
||||||
[]
|
|
||||||
}
|
|
||||||
packageOptions {
|
|
||||||
prefix = "com.willowtreeapps.fuzzywuzzy"
|
|
||||||
suppress = true
|
|
||||||
}
|
|
||||||
sourceRoot {
|
|
||||||
// assuming there is only a single source dir...
|
|
||||||
path = kotlin.sourceSets.commonMain.kotlin.srcDirs[0]
|
|
||||||
platforms = ["Common"]
|
|
||||||
}
|
|
||||||
if (kotlin.sourceSets.getNames().contains("jvmMain")) {
|
|
||||||
sourceRoot {
|
|
||||||
// assuming there is only a single source dir...
|
|
||||||
path = kotlin.sourceSets.jvmMain.kotlin.srcDirs[0]
|
|
||||||
platforms = ["JVM"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (kotlin.sourceSets.getNames().contains("jsMain")) {
|
|
||||||
sourceRoot {
|
|
||||||
// assuming there is only a single source dir...
|
|
||||||
path = kotlin.sourceSets.jsMain.kotlin.srcDirs[0]
|
|
||||||
platforms = ["js"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (kotlin.sourceSets.getNames().contains("nativeMain")) {
|
|
||||||
sourceRoot {
|
|
||||||
// assuming there is only a single source dir...
|
|
||||||
path = kotlin.sourceSets.nativeMain.kotlin.srcDirs[0]
|
|
||||||
platforms = ["native"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def isReleaseBuild() {
|
|
||||||
return VERSION_NAME.contains("SNAPSHOT") == false
|
|
||||||
}
|
|
||||||
|
|
||||||
def getReleaseRepositoryUrl() {
|
|
||||||
return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL :
|
|
||||||
"https://oss.sonatype.org/service/local/staging/deploy/maven2/"
|
|
||||||
}
|
|
||||||
|
|
||||||
def getSnapshotRepositoryUrl() {
|
|
||||||
return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL :
|
|
||||||
"https://oss.sonatype.org/content/repositories/snapshots/"
|
|
||||||
}
|
|
||||||
|
|
||||||
def getRepositoryUsername() {
|
|
||||||
return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : ""
|
|
||||||
}
|
|
||||||
|
|
||||||
def getRepositoryPassword() {
|
|
||||||
return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : ""
|
|
||||||
}
|
|
||||||
|
|
||||||
task emptySourcesJar(type: Jar) {
|
|
||||||
classifier = 'sources'
|
|
||||||
}
|
|
||||||
|
|
||||||
task javadocsJar(type: Jar, dependsOn: dokka) {
|
|
||||||
classifier = 'javadoc'
|
|
||||||
from dokka.outputDirectory
|
|
||||||
}
|
|
||||||
|
|
||||||
signing {
|
|
||||||
required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
|
|
||||||
sign(publishing.publications)
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications.all {
|
|
||||||
artifact javadocsJar
|
|
||||||
|
|
||||||
pom.withXml {
|
|
||||||
def root = asNode()
|
|
||||||
|
|
||||||
root.children().last() + {
|
|
||||||
resolveStrategy = Closure.DELEGATE_FIRST
|
|
||||||
|
|
||||||
description POM_DESCRIPTION
|
|
||||||
name POM_NAME
|
|
||||||
url POM_URL
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name POM_LICENCE_NAME
|
|
||||||
url POM_LICENCE_URL
|
|
||||||
distribution POM_LICENCE_DIST
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
url POM_SCM_URL
|
|
||||||
connection POM_SCM_CONNECTION
|
|
||||||
developerConnection POM_SCM_DEV_CONNECTION
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id POM_DEVELOPER_ID
|
|
||||||
name POM_DEVELOPER_NAME
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
publications.getByName('kotlinMultiplatform') {
|
|
||||||
// Source jars are only created for platforms, not the common artifact.
|
|
||||||
artifact emptySourcesJar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url isReleaseBuild() ? getReleaseRepositoryUrl() : getSnapshotRepositoryUrl()
|
|
||||||
credentials {
|
|
||||||
username getRepositoryUsername()
|
|
||||||
password getRepositoryPassword()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maven {
|
|
||||||
name 'test'
|
|
||||||
url "file://${rootProject.buildDir}/localMaven"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
BIN
fuzzywuzzy/gradle/wrapper/gradle-wrapper.jar
vendored
BIN
fuzzywuzzy/gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
@ -1,22 +0,0 @@
|
|||||||
#
|
|
||||||
# * Copyright (c) 2021 Shabinder Singh
|
|
||||||
# * This program is free software: you can redistribute it and/or modify
|
|
||||||
# * it under the terms of the GNU General Public License as published by
|
|
||||||
# * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# * (at your option) any later version.
|
|
||||||
# *
|
|
||||||
# * This program is distributed in the hope that it will be useful,
|
|
||||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# * GNU General Public License for more details.
|
|
||||||
# *
|
|
||||||
# * You should have received a copy of the GNU General Public License
|
|
||||||
# * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
#Wed Apr 17 16:40:04 EDT 2019
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
|
||||||
distributionPath=wrapper/dists
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.3.1-all.zip
|
|
188
fuzzywuzzy/gradlew
vendored
188
fuzzywuzzy/gradlew
vendored
@ -1,188 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
#
|
|
||||||
# * Copyright (c) 2021 Shabinder Singh
|
|
||||||
# * This program is free software: you can redistribute it and/or modify
|
|
||||||
# * it under the terms of the GNU General Public License as published by
|
|
||||||
# * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# * (at your option) any later version.
|
|
||||||
# *
|
|
||||||
# * This program is distributed in the hope that it will be useful,
|
|
||||||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# * GNU General Public License for more details.
|
|
||||||
# *
|
|
||||||
# * You should have received a copy of the GNU General Public License
|
|
||||||
# * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
|
||||||
##
|
|
||||||
## Gradle start up script for UN*X
|
|
||||||
##
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
|
||||||
# Resolve links: $0 may be a link
|
|
||||||
PRG="$0"
|
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD="maximum"
|
|
||||||
|
|
||||||
warn () {
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
nonstop=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="java"
|
|
||||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
location of your Java installation."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
|
||||||
if [ $? -eq 0 ] ; then
|
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
ulimit -n $MAX_FD
|
|
||||||
if [ $? -ne 0 ] ; then
|
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin ; then
|
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
|
||||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=$((i+1))
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
(0) set -- ;;
|
|
||||||
(1) set -- "$args0" ;;
|
|
||||||
(2) set -- "$args0" "$args1" ;;
|
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Escape application args
|
|
||||||
save () {
|
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
|
||||||
echo " "
|
|
||||||
}
|
|
||||||
APP_ARGS=$(save "$@")
|
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
|
84
fuzzywuzzy/gradlew.bat
vendored
84
fuzzywuzzy/gradlew.bat
vendored
@ -1,84 +0,0 @@
|
|||||||
@if "%DEBUG%" == "" @echo off
|
|
||||||
@rem ##########################################################################
|
|
||||||
@rem
|
|
||||||
@rem Gradle startup script for Windows
|
|
||||||
@rem
|
|
||||||
@rem ##########################################################################
|
|
||||||
|
|
||||||
@rem Set local scope for the variables with windows NT shell
|
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
|
||||||
set APP_BASE_NAME=%~n0
|
|
||||||
set APP_HOME=%DIRNAME%
|
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
set DEFAULT_JVM_OPTS=
|
|
||||||
|
|
||||||
@rem Find java.exe
|
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:findJavaFromJavaHome
|
|
||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
|
||||||
echo.
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
|
||||||
echo location of your Java installation.
|
|
||||||
|
|
||||||
goto fail
|
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
|
||||||
@rem Setup the command line
|
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
|
||||||
|
|
||||||
:end
|
|
||||||
@rem End local scope for the variables with windows NT shell
|
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
|
||||||
|
|
||||||
:fail
|
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
|
||||||
rem the _cmd.exe /c_ return code!
|
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
|
||||||
exit /b 1
|
|
||||||
|
|
||||||
:mainEnd
|
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
|
||||||
|
|
||||||
:omega
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* * Copyright (c) 2021 Shabinder Singh
|
|
||||||
* * This program is free software: you can redistribute it and/or modify
|
|
||||||
* * it under the terms of the GNU General Public License as published by
|
|
||||||
* * the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* * (at your option) any later version.
|
|
||||||
* *
|
|
||||||
* * This program is distributed in the hope that it will be useful,
|
|
||||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* * GNU General Public License for more details.
|
|
||||||
* *
|
|
||||||
* * You should have received a copy of the GNU General Public License
|
|
||||||
* * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pluginManagement {
|
|
||||||
resolutionStrategy {
|
|
||||||
eachPlugin {
|
|
||||||
if (requested.id.id == "kotlin-multiplatform") {
|
|
||||||
useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${requested.version}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
include ':app'
|
|
||||||
rootProject.name='fuzzywuzzy'
|
|
||||||
|
|
||||||
|
|
||||||
rootProject.name = 'test'
|
|
||||||
enableFeaturePreview('GRADLE_METADATA')
|
|
||||||
enableFeaturePreview('STABLE_PUBLISHING')
|
|
||||||
|
|
@ -39,7 +39,6 @@ org.gradle.parallel=true
|
|||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
kotlin.native.disableCompilerDaemon=true
|
kotlin.native.disableCompilerDaemon=true
|
||||||
kotlin.mpp.stability.nowarn=true
|
kotlin.mpp.stability.nowarn=true
|
||||||
#android.useAndroidX=true
|
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||||
#kotlin.mpp.enableGranularSourceSetsMetadata=true
|
kotlin.native.enableDependencyPropagation=false
|
||||||
#kotlin.native.enableDependencyPropagation=false
|
|
||||||
#org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
#org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=1024m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
|
@ -50,9 +50,9 @@ class ListScreen(
|
|||||||
id = "list-screen"
|
id = "list-screen"
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null){
|
if(result == null) {
|
||||||
LoadingAnim { }
|
LoadingAnim { }
|
||||||
}else{
|
}else {
|
||||||
CoverImage {
|
CoverImage {
|
||||||
coverImageURL = result.coverUrl
|
coverImageURL = result.coverUrl
|
||||||
coverName = result.title
|
coverName = result.title
|
||||||
@ -66,7 +66,7 @@ class ListScreen(
|
|||||||
link = state.data.link
|
link = state.data.link
|
||||||
}
|
}
|
||||||
|
|
||||||
styledDiv{
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
display =Display.flex
|
display =Display.flex
|
||||||
flexGrow = 1.0
|
flexGrow = 1.0
|
||||||
|
@ -1 +1,17 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="100%" height="100%" x="0" y="0" preserveAspectRatio="xMinYMin" version="1.1" viewBox="0 0 192 192" xml:space="preserve"><g id="XMLID_167_"><circle id="XMLID_791_" cx="96" cy="96" r="88" fill="red"/><g id="XMLID_41_"><path id="XMLID_42_" fill="#FFF" d="M96,54.04c23.14,0,41.96,18.82,41.96,41.96S119.14,137.96,96,137.96S54.04,119.14,54.04,96 S72.86,54.04,96,54.04 M96,50c-25.41,0-46,20.59-46,46s20.59,46,46,46s46-20.59,46-46S121.41,50,96,50L96,50z"/></g><polygon id="XMLID_274_" fill="#FFF" points="80 119 119 95 80 73"/></g></svg>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1076.1 1080" style="enable-background:new 0 0 1076.1 1080;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#FF0000;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
</style>
|
||||||
|
<g id="XMLID_167_">
|
||||||
|
<circle id="XMLID_791_" class="st0" cx="540" cy="540" r="495"/>
|
||||||
|
<g id="XMLID_41_">
|
||||||
|
<path id="XMLID_42_" class="st1" d="M540,304c130.2,0,236,105.9,236,236S670.2,776,540,776S304,670.2,304,540S409.8,304,540,304
|
||||||
|
M540,281.2c-142.9,0-258.8,115.8-258.8,258.8S397.1,798.8,540,798.8S798.8,682.9,798.8,540S682.9,281.2,540,281.2L540,281.2z"/>
|
||||||
|
</g>
|
||||||
|
<polygon id="XMLID_274_" class="st1" points="450,669.4 669.4,534.4 450,410.6 "/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 632 B After Width: | Height: | Size: 893 B |
Loading…
Reference in New Issue
Block a user