forked from MapComplete/MapComplete
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
|
import Locale from "../../UI/i18n/Locale"
|
||
|
import { Utils } from "../../Utils"
|
||
|
import ThemeSearch from "./ThemeSearch"
|
||
|
|
||
|
export default class SearchUtils {
|
||
|
|
||
|
|
||
|
/** Applies special search terms, such as 'studio', 'osmcha', ...
|
||
|
* Returns 'false' if nothing is matched.
|
||
|
* Doesn't return control flow if a match is found (navigates to another page in this case)
|
||
|
*/
|
||
|
public static applySpecialSearch(searchTerm: string, ) {
|
||
|
searchTerm = searchTerm.toLowerCase()
|
||
|
if (!searchTerm) {
|
||
|
return false
|
||
|
}
|
||
|
if (searchTerm === "personal") {
|
||
|
window.location.href = ThemeSearch.createUrlFor({ id: "personal" }, undefined)
|
||
|
}
|
||
|
if (searchTerm === "bugs" || searchTerm === "issues") {
|
||
|
window.location.href = "https://github.com/pietervdvn/MapComplete/issues"
|
||
|
}
|
||
|
if (searchTerm === "source") {
|
||
|
window.location.href = "https://github.com/pietervdvn/MapComplete"
|
||
|
}
|
||
|
if (searchTerm === "docs") {
|
||
|
window.location.href = "https://github.com/pietervdvn/MapComplete/tree/develop/Docs"
|
||
|
}
|
||
|
if (searchTerm === "osmcha" || searchTerm === "stats") {
|
||
|
window.location.href = Utils.OsmChaLinkFor(7)
|
||
|
}
|
||
|
if (searchTerm === "studio") {
|
||
|
window.location.href = "./studio.html"
|
||
|
}
|
||
|
return false
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Searches for the smallest distance in words; will split both the query and the terms
|
||
|
*
|
||
|
* SearchUtils.scoreKeywords("drinking water", {"en": ["A layer with drinking water points"]}, "en") // => 0
|
||
|
* SearchUtils.scoreKeywords("waste", {"en": ["A layer with drinking water points"]}, "en") // => 2
|
||
|
*
|
||
|
*/
|
||
|
public static scoreKeywords(query: string, keywords: Record<string, string[]> | string[], language?: string): number {
|
||
|
if(!keywords){
|
||
|
return Infinity
|
||
|
}
|
||
|
language ??= Locale.language.data
|
||
|
const queryParts = query.trim().split(" ").map(q => Utils.simplifyStringForSearch(q))
|
||
|
let terms: string[]
|
||
|
if (Array.isArray(keywords)) {
|
||
|
terms = keywords
|
||
|
} else {
|
||
|
terms = (keywords[language] ?? []).concat(keywords["*"])
|
||
|
}
|
||
|
const termsAll = Utils.NoNullInplace(terms).flatMap(t => t.split(" "))
|
||
|
|
||
|
let distanceSummed = 0
|
||
|
for (let i = 0; i < queryParts.length; i++) {
|
||
|
const q = queryParts[i]
|
||
|
let minDistance: number = 99
|
||
|
for (const term of termsAll) {
|
||
|
const d = Utils.levenshteinDistance(q, Utils.simplifyStringForSearch(term))
|
||
|
if (d < minDistance) {
|
||
|
minDistance = d
|
||
|
}
|
||
|
}
|
||
|
distanceSummed += minDistance
|
||
|
}
|
||
|
return distanceSummed
|
||
|
}
|
||
|
}
|