001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.util; 020 021import java.util.ArrayList; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.function.Function; 025 026/** 027 * String comparison library. 028 */ 029public class StringComparison<T> { 030 031 private final Function<T, String> toString; 032 private T bestMatch; 033 private double match = Integer.MAX_VALUE; 034 private T bestMatchObject; 035 036 /** 037 * Constructor 038 * 039 * @param input Input Base Value 040 * @param objects Objects to compare 041 */ 042 public StringComparison(String input, T[] objects) { 043 this(input, objects, Object::toString); 044 } 045 046 public StringComparison(String input, T[] objects, Function<T, String> toString) { 047 this.toString = toString; 048 init(input, objects); 049 } 050 051 public StringComparison(String input, Collection<T> objects) { 052 this(input, objects, Object::toString); 053 } 054 055 @SuppressWarnings("unchecked") 056 public StringComparison(String input, Collection<T> objects, Function<T, String> toString) { 057 this(input, (T[]) objects.toArray(), toString); 058 } 059 060 /** 061 * You should call init(...) when you are ready to get a String comparison value. 062 */ 063 public StringComparison() { 064 this.toString = Object::toString; 065 } 066 067 /** 068 * Compare two strings 069 * 070 * @param s1 String Base 071 * @param s2 Object 072 * @return match 073 */ 074 public static int compare(String s1, String s2) { 075 int distance = StringMan.getLevenshteinDistance(s1, s2); 076 if (s2.contains(s1)) { 077 distance -= Math.min(s1.length(), s2.length()); 078 } 079 if (s2.startsWith(s1)) { 080 distance -= 4; 081 } 082 return distance; 083 } 084 085 /** 086 * Create an ArrayList containing pairs of letters 087 * 088 * @param s string to split 089 * @return ArrayList 090 */ 091 public static ArrayList<String> wLetterPair(String s) { 092 ArrayList<String> aPairs = new ArrayList<>(); 093 String[] wo = s.split("\\s"); 094 for (String aWo : wo) { 095 String[] po = sLetterPair(aWo); 096 Collections.addAll(aPairs, po); 097 } 098 return aPairs; 099 } 100 101 /** 102 * Get an array containing letter pairs 103 * 104 * @param s string to split 105 * @return Array 106 */ 107 public static String[] sLetterPair(String s) { 108 int numPair = s.length() - 1; 109 String[] p = new String[numPair]; 110 for (int i = 0; i < numPair; i++) { 111 p[i] = s.substring(i, i + 2); 112 } 113 return p; 114 } 115 116 public void init(String input, T[] objects) { 117 int c; 118 this.bestMatch = objects[0]; 119 this.bestMatchObject = objects[0]; 120 input = input.toLowerCase(); 121 for (T o : objects) { 122 if ((c = compare(input, getString(o).toLowerCase())) < this.match) { 123 this.match = c; 124 this.bestMatch = o; 125 this.bestMatchObject = o; 126 } 127 } 128 } 129 130 public String getString(T o) { 131 return this.toString.apply(o); 132 } 133 134 /** 135 * Get the object 136 * 137 * @return match object 138 */ 139 public T getMatchObject() { 140 return this.bestMatchObject; 141 } 142 143 /** 144 * Get the best match value 145 * 146 * @return match value 147 */ 148 public String getBestMatch() { 149 return getString(this.bestMatch); 150 } 151 152 /** 153 * Will return both the match number, and the actual match string 154 * 155 * @return object[] containing: double, String 156 */ 157 public ComparisonResult getBestMatchAdvanced() { 158 return new ComparisonResult(this.match, this.bestMatch); 159 } 160 161 162 /** 163 * The comparison result 164 */ 165 public class ComparisonResult { 166 167 public final T best; 168 public final double match; 169 170 /** 171 * The constructor 172 * 173 * @param match Match value 174 * @param best Best Match 175 */ 176 public ComparisonResult(double match, T best) { 177 this.match = match; 178 this.best = best; 179 } 180 181 } 182 183}