mirror of
https://github.com/Shabinder/SpotiFlyer.git
synced 2024-12-22 20:57:54 +01:00
FuzzyWuzzy KMP added.
This commit is contained in:
parent
1f773c3493
commit
cc4362963a
@ -11,6 +11,9 @@ allprojects {
|
||||
maven(url = "https://dl.bintray.com/ekito/koin")
|
||||
maven(url = "https://kotlin.bintray.com/kotlin-js-wrappers/")
|
||||
maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||
flatDir {
|
||||
dirs("fuzzywuzzy")
|
||||
}
|
||||
}
|
||||
}
|
||||
buildscript {
|
||||
|
@ -12,6 +12,7 @@ buildscript{
|
||||
mavenLocal()
|
||||
google()
|
||||
jcenter()
|
||||
maven(url = "https://jitpack.io")
|
||||
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||
}
|
||||
|
||||
@ -23,7 +24,8 @@ buildscript{
|
||||
}
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven(url = "https://jitpack.io")
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
google()
|
||||
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||
|
@ -10,6 +10,7 @@ kotlin {
|
||||
dependencies {
|
||||
implementation(project(":common:data-models"))
|
||||
implementation(project(":common:database"))
|
||||
implementation(project(":fuzzywuzzy:app"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
|
||||
implementation(Ktor.clientCore)
|
||||
implementation(Ktor.clientCio)
|
||||
@ -24,7 +25,8 @@ kotlin {
|
||||
api(Extras.kermit)
|
||||
api(Extras.jsonKlaxon)
|
||||
api(Extras.youtubeDownloader)
|
||||
api(Extras.fuzzyWuzzy)
|
||||
//api(Extras.fuzzyWuzzy)
|
||||
//api("com.github.willowtreeapps:fuzzywuzzy-kotlin:v0.1.1")
|
||||
}
|
||||
}
|
||||
androidMain {
|
||||
|
@ -2,17 +2,16 @@ package com.shabinder.common
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.shabinder.common.YoutubeTrack
|
||||
import com.beust.klaxon.JsonArray
|
||||
import com.beust.klaxon.JsonObject
|
||||
import com.beust.klaxon.Parser
|
||||
import com.willowtreeapps.fuzzywuzzy.diffutils.FuzzySearch
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import kotlinx.serialization.json.putJsonObject
|
||||
import me.xdrop.fuzzywuzzy.FuzzySearch
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
private const val apiKey = "AIzaSyC9XL3ZjWddXya6X74dJoCTL-WEYFDNX30"
|
||||
@ -199,12 +198,12 @@ actual class YoutubeMusic actual constructor(
|
||||
|
||||
if(result.type == "Song"){
|
||||
for (artist in trackArtists){
|
||||
if(FuzzySearch.ratio(artist.toLowerCase(),result.artist?.toLowerCase()) > 85)
|
||||
if(FuzzySearch.ratio(artist.toLowerCase(),result.artist?.toLowerCase() ?: "") > 85)
|
||||
artistMatchNumber++
|
||||
}
|
||||
}else{//i.e. is a Video
|
||||
for (artist in trackArtists) {
|
||||
if(FuzzySearch.partialRatio(artist.toLowerCase(),result.name?.toLowerCase()) > 85)
|
||||
if(FuzzySearch.partialRatio(artist.toLowerCase(),result.name?.toLowerCase() ?: "") > 85)
|
||||
artistMatchNumber++
|
||||
}
|
||||
}
|
||||
|
42
fuzzywuzzy/.circleci/config.yml
Normal file
42
fuzzywuzzy/.circleci/config.yml
Normal file
@ -0,0 +1,42 @@
|
||||
# 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
|
201
fuzzywuzzy/LICENSE
Normal file
201
fuzzywuzzy/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
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.
|
44
fuzzywuzzy/README.md
Normal file
44
fuzzywuzzy/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# 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
|
193
fuzzywuzzy/app/build.gradle
Normal file
193
fuzzywuzzy/app/build.gradle
Normal file
@ -0,0 +1,193 @@
|
||||
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() {
|
||||
[compileKotlinJs, compileTestKotlinJs].each { configuration ->
|
||||
configuration.kotlinOptions {
|
||||
moduleKind = 'umd'
|
||||
sourceMap = true
|
||||
metaInfo = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iosArm64("ios")
|
||||
iosX64("iosSim")
|
||||
macosX64("macos")
|
||||
mingwX64("win")
|
||||
wasm32("wasm")
|
||||
linuxArm32Hfp("linArm32")
|
||||
linuxMips32("linMips32")
|
||||
linuxMipsel32("linMipsel32")
|
||||
linuxX64("lin64")
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
dependencies {
|
||||
implementation kotlin("stdlib-common")
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
kotlin.srcDir('src/test')
|
||||
dependencies {
|
||||
implementation kotlin("test-common")
|
||||
implementation kotlin("test-annotations-common")
|
||||
}
|
||||
}
|
||||
|
||||
jvmMain {
|
||||
kotlin.srcDir('src/jvmMain/kotlin')
|
||||
dependencies {
|
||||
implementation kotlin("stdlib")
|
||||
}
|
||||
}
|
||||
jvmTest {
|
||||
dependencies {
|
||||
implementation kotlin("test")
|
||||
implementation kotlin("test-junit")
|
||||
implementation 'junit:junit:4.12'
|
||||
}
|
||||
}
|
||||
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"
|
||||
}
|
||||
}
|
||||
jsTest {
|
||||
dependencies {
|
||||
implementation kotlin("test-js")
|
||||
implementation kotlin("stdlib-js")
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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
Normal file
853
fuzzywuzzy/app/package-lock.json
generated
Normal file
@ -0,0 +1,853 @@
|
||||
{
|
||||
"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
Normal file
21
fuzzywuzzy/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# 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
|
@ -0,0 +1,29 @@
|
||||
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
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
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
|
||||
|
||||
}
|
@ -0,0 +1,847 @@
|
||||
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.*
|
||||
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
|
||||
val len2o: Int
|
||||
var i = 0
|
||||
|
||||
val matrix: IntArray
|
||||
|
||||
val c1 = s1
|
||||
val c2 = s2
|
||||
|
||||
var p1 = 0
|
||||
var p2 = 0
|
||||
|
||||
while (len1Copy > 0 && len2Copy > 0 && c1[p1] == c2[p2]) {
|
||||
len1Copy--
|
||||
len2Copy--
|
||||
|
||||
p1++
|
||||
p2++
|
||||
|
||||
len1o++
|
||||
}
|
||||
|
||||
len2o = len1o
|
||||
|
||||
/* strip common suffix */
|
||||
while (len1Copy > 0 && len2Copy > 0 && c1[p1 + len1Copy - 1] == c2[p2 + len2Copy - 1]) {
|
||||
len1Copy--
|
||||
len2Copy--
|
||||
}
|
||||
|
||||
len1Copy++
|
||||
len2Copy++
|
||||
|
||||
matrix = 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 = c1[p1 + i - 1]
|
||||
var ptrChar2 = p2
|
||||
|
||||
var x = i
|
||||
|
||||
ptrC++
|
||||
|
||||
while (ptrC <= ptrEnd) {
|
||||
|
||||
var c3 = matrix[ptrPrev++] + if (char1 != c2[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, c1, p1, len1o, len2Copy, c2, 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
|
||||
|
||||
val ops: Array<EditOp?>
|
||||
|
||||
var dir = 0
|
||||
|
||||
ops = 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 i: Int
|
||||
var o = 0
|
||||
|
||||
i = 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 i: Int
|
||||
var spos: Int
|
||||
var dpos: Int
|
||||
|
||||
var o = 0
|
||||
|
||||
dpos = 0
|
||||
spos = dpos
|
||||
|
||||
var type: EditType
|
||||
|
||||
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) {
|
||||
|
||||
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()
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
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.max()!!
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.max()!!
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
}
|
@ -0,0 +1,754 @@
|
||||
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
|
||||
*/
|
||||
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())
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
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
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
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
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
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`
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
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)
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
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.max()!!
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
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 <= ' ' }
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
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
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
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)
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
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)"
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
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.max()!!).toInt()
|
||||
|
||||
}
|
||||
|
||||
override fun apply(s1: String, s2: String, sp: ToStringFunction<String>): Int {
|
||||
return apply(sp.apply(s1), sp.apply(s2))
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
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))
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
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
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
package com.willowtreeapps.fuzzywuzzy.algorithms
|
||||
|
@ -0,0 +1,5 @@
|
||||
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]"""
|
||||
|
@ -0,0 +1,3 @@
|
||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
||||
|
||||
actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
@ -0,0 +1,4 @@
|
||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
||||
|
||||
//actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
||||
actual val pattern: String = """/[\W]*/"""
|
@ -0,0 +1,56 @@
|
||||
package com.willowtreeapps.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")
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package com.willowtreeapps.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)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
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))
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package com.willowtreeapps.fuzzywuzzy.diffutils.algorithms
|
||||
|
||||
actual val pattern: String = "(?U)[^\\p{Alnum}]"
|
49
fuzzywuzzy/build.gradle
Normal file
49
fuzzywuzzy/build.gradle
Normal file
@ -0,0 +1,49 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
39
fuzzywuzzy/gradle.properties
Normal file
39
fuzzywuzzy/gradle.properties
Normal file
@ -0,0 +1,39 @@
|
||||
# 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.
|
14
fuzzywuzzy/gradle/dependencies.gradle
Normal file
14
fuzzywuzzy/gradle/dependencies.gradle
Normal file
@ -0,0 +1,14 @@
|
||||
ext.versions = [
|
||||
kotlin : '1.3.30',
|
||||
kotlinCoroutines: '1.2.0',
|
||||
dokka : '0.9.17',
|
||||
nodePlugin: '1.2.0'
|
||||
]
|
||||
ext.deps = [
|
||||
plugins: [
|
||||
android: 'com.android.tools.build:gradle:3.3.0',
|
||||
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}"
|
||||
]
|
||||
]
|
29
fuzzywuzzy/gradle/pom.gradle
Normal file
29
fuzzywuzzy/gradle/pom.gradle
Normal file
@ -0,0 +1,29 @@
|
||||
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
|
||||
}
|
137
fuzzywuzzy/gradle/publish.gradle
Normal file
137
fuzzywuzzy/gradle/publish.gradle
Normal file
@ -0,0 +1,137 @@
|
||||
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
Normal file
BIN
fuzzywuzzy/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
fuzzywuzzy/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
fuzzywuzzy/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#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
|
172
fuzzywuzzy/gradlew
vendored
Executable file
172
fuzzywuzzy/gradlew
vendored
Executable file
@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## 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
Normal file
84
fuzzywuzzy/gradlew.bat
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
@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
|
18
fuzzywuzzy/settings.gradle
Normal file
18
fuzzywuzzy/settings.gradle
Normal file
@ -0,0 +1,18 @@
|
||||
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')
|
||||
|
@ -3,6 +3,7 @@ pluginManagement {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
maven(url = "https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||
maven(url = "https://jitpack.io")
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +15,7 @@ include(
|
||||
":common:compose-ui",
|
||||
":common:data-models",
|
||||
":common:dependency-injection",
|
||||
":fuzzywuzzy:app",
|
||||
":android",
|
||||
":desktop"
|
||||
)
|
Loading…
Reference in New Issue
Block a user