mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-10 12:26:16 -04:00
* Fix #1549 * Revert changes on ModTranslations. * Revert changes on StringUtils.
This commit is contained in:
parent
8678c0dcf2
commit
532ba6ec2f
@ -21,17 +21,18 @@ import org.jackhuang.hmcl.mod.LocalModFile;
|
|||||||
import org.jackhuang.hmcl.mod.RemoteMod;
|
import org.jackhuang.hmcl.mod.RemoteMod;
|
||||||
import org.jackhuang.hmcl.mod.RemoteModRepository;
|
import org.jackhuang.hmcl.mod.RemoteModRepository;
|
||||||
import org.jackhuang.hmcl.ui.versions.ModTranslations;
|
import org.jackhuang.hmcl.ui.versions.ModTranslations;
|
||||||
import org.jackhuang.hmcl.util.Lang;
|
|
||||||
import org.jackhuang.hmcl.util.Pair;
|
import org.jackhuang.hmcl.util.Pair;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||||
|
|
||||||
public abstract class LocalizedRemoteModRepository implements RemoteModRepository {
|
public abstract class LocalizedRemoteModRepository implements RemoteModRepository {
|
||||||
// Yes, I'm not kidding you. The similarity check is based on these two magic number. :)
|
|
||||||
private static final int CONTAIN_CHINESE_WEIGHT = 10;
|
private static final int CONTAIN_CHINESE_WEIGHT = 10;
|
||||||
|
|
||||||
private static final int INITIAL_CAPACITY = 16;
|
private static final int INITIAL_CAPACITY = 16;
|
||||||
@ -62,45 +63,45 @@ public abstract class LocalizedRemoteModRepository implements RemoteModRepositor
|
|||||||
if (count >= 3) break;
|
if (count >= 3) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchResult searchResult = getBackedRemoteModRepository().search(gameVersion, category, pageOffset, pageSize, String.join(" ", englishSearchFiltersSet), getBackedRemoteModRepositorySortOrder(), sortOrder);
|
|
||||||
|
|
||||||
RemoteMod[] searchResultArray = new RemoteMod[pageSize];
|
RemoteMod[] searchResultArray = new RemoteMod[pageSize];
|
||||||
int chineseIndex = 0, englishIndex = searchResultArray.length - 1;
|
int totalPages, chineseIndex = 0, englishIndex = pageSize - 1;
|
||||||
for (RemoteMod remoteMod : Lang.toIterable(searchResult.getUnsortedResults())) {
|
{
|
||||||
if (chineseIndex > englishIndex) {
|
SearchResult searchResult = getBackedRemoteModRepository().search(gameVersion, category, pageOffset, pageSize, String.join(" ", englishSearchFiltersSet), getBackedRemoteModRepositorySortOrder(), sortOrder);
|
||||||
throw new IOException("There are too many search results!");
|
for (Iterator<RemoteMod> iterator = searchResult.getUnsortedResults().iterator(); iterator.hasNext(); ) {
|
||||||
}
|
if (chineseIndex > englishIndex) {
|
||||||
|
LOG.log(Level.WARNING, "Too many search results! Are the backed remote mod repository broken? Or are the API broken?");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ModTranslations.Mod chineseTranslation = ModTranslations.getTranslationsByRepositoryType(getType()).getModByCurseForgeId(remoteMod.getSlug());
|
RemoteMod remoteMod = iterator.next();
|
||||||
if (chineseTranslation != null && !StringUtils.isBlank(chineseTranslation.getName()) && StringUtils.containsChinese(chineseTranslation.getName())) {
|
ModTranslations.Mod chineseTranslation = ModTranslations.getTranslationsByRepositoryType(getType()).getModByCurseForgeId(remoteMod.getSlug());
|
||||||
searchResultArray[chineseIndex++] = remoteMod;
|
if (chineseTranslation != null && !StringUtils.isBlank(chineseTranslation.getName()) && StringUtils.containsChinese(chineseTranslation.getName())) {
|
||||||
} else {
|
searchResultArray[chineseIndex++] = remoteMod;
|
||||||
searchResultArray[englishIndex--] = remoteMod;
|
} else {
|
||||||
|
searchResultArray[englishIndex--] = remoteMod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
totalPages = searchResult.getTotalPages();
|
||||||
}
|
}
|
||||||
int totalPages = searchResult.getTotalPages();
|
|
||||||
searchResult = null; // Release memory
|
|
||||||
|
|
||||||
StringUtils.DynamicCommonSubsequence calc = new StringUtils.DynamicCommonSubsequence(16, 16);
|
StringUtils.LevCalculator levCalculator = new StringUtils.LevCalculator();
|
||||||
return new SearchResult(Stream.concat(Arrays.stream(searchResultArray, 0, chineseIndex).map(remoteMod -> {
|
return new SearchResult(Stream.concat(Arrays.stream(searchResultArray, 0, chineseIndex).map(remoteMod -> {
|
||||||
ModTranslations.Mod chineseRemoteMod = ModTranslations.getTranslationsByRepositoryType(getType()).getModByCurseForgeId(remoteMod.getSlug());
|
ModTranslations.Mod chineseRemoteMod = ModTranslations.getTranslationsByRepositoryType(getType()).getModByCurseForgeId(remoteMod.getSlug());
|
||||||
if (chineseRemoteMod == null || StringUtils.isBlank(chineseRemoteMod.getName()) || !StringUtils.containsChinese(chineseRemoteMod.getName())) {
|
if (chineseRemoteMod == null || StringUtils.isBlank(chineseRemoteMod.getName()) || !StringUtils.containsChinese(chineseRemoteMod.getName())) {
|
||||||
return Pair.pair(remoteMod, Integer.MAX_VALUE);
|
return Pair.pair(remoteMod, Integer.MAX_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
String chineseRemoteModName = chineseRemoteMod.getName();
|
String chineseRemoteModName = chineseRemoteMod.getName();
|
||||||
if (searchFilter.isEmpty() || chineseRemoteModName.isEmpty()) {
|
if (searchFilter.isEmpty() || chineseRemoteModName.isEmpty()) {
|
||||||
return Pair.pair(remoteMod, Math.max(searchFilter.length(), chineseRemoteModName.length()));
|
return Pair.pair(remoteMod, Math.max(searchFilter.length(), chineseRemoteModName.length()));
|
||||||
}
|
}
|
||||||
|
int l = levCalculator.calc(searchFilter, chineseRemoteModName);
|
||||||
int weight = calc.calc(searchFilter, chineseRemoteModName);
|
for (int i = 0; i < searchFilter.length(); i++) {
|
||||||
for (int i = 0;i < searchFilter.length(); i ++) {
|
|
||||||
if (chineseRemoteModName.indexOf(searchFilter.charAt(i)) >= 0) {
|
if (chineseRemoteModName.indexOf(searchFilter.charAt(i)) >= 0) {
|
||||||
return Pair.pair(remoteMod, weight + CONTAIN_CHINESE_WEIGHT);
|
l -= CONTAIN_CHINESE_WEIGHT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Pair.pair(remoteMod, weight);
|
return Pair.pair(remoteMod, l);
|
||||||
}).sorted(Comparator.<Pair<RemoteMod, Integer>>comparingInt(Pair::getValue).reversed()).map(Pair::getKey), Arrays.stream(searchResultArray, englishIndex + 1, searchResultArray.length)), totalPages);
|
}).sorted(Comparator.comparingInt(Pair::getValue)).map(Pair::getKey), Arrays.stream(searchResultArray, englishIndex + 1, searchResultArray.length)), totalPages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -112,7 +112,7 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
.getJson(new TypeToken<Response<List<CurseAddon>>>() {
|
.getJson(new TypeToken<Response<List<CurseAddon>>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
Stream<RemoteMod> res = response.getData().stream().map(CurseAddon::toMod);
|
Stream<RemoteMod> res = response.getData().stream().map(CurseAddon::toMod);
|
||||||
if (sortType != SortType.NAME || searchFilter.length() == 0) {
|
if (sortType != SortType.NAME || searchFilter.isEmpty()) {
|
||||||
return new SearchResult(res, (int)Math.ceil((double)response.pagination.totalCount / pageSize));
|
return new SearchResult(res, (int)Math.ceil((double)response.pagination.totalCount / pageSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,25 +123,11 @@ public final class CurseForgeRemoteModRepository implements RemoteModRepository
|
|||||||
searchFilterWords.put(s, searchFilterWords.getOrDefault(s, 0) + 1);
|
searchFilterWords.put(s, searchFilterWords.getOrDefault(s, 0) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringUtils.LevCalculator levCalculator = new StringUtils.LevCalculator();
|
||||||
|
|
||||||
return new SearchResult(res.map(remoteMod -> {
|
return new SearchResult(res.map(remoteMod -> {
|
||||||
String lowerCaseResult = remoteMod.getTitle().toLowerCase();
|
String lowerCaseResult = remoteMod.getTitle().toLowerCase();
|
||||||
int[][] lev = new int[lowerCaseSearchFilter.length() + 1][lowerCaseResult.length() + 1];
|
int diff = levCalculator.calc(lowerCaseSearchFilter, lowerCaseResult);
|
||||||
for (int i = 0; i < lowerCaseResult.length() + 1; i++) {
|
|
||||||
lev[0][i] = i;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < lowerCaseSearchFilter.length() + 1; i++) {
|
|
||||||
lev[i][0] = i;
|
|
||||||
}
|
|
||||||
for (int i = 1; i < lowerCaseSearchFilter.length() + 1; i++) {
|
|
||||||
for (int j = 1; j < lowerCaseResult.length() + 1; j++) {
|
|
||||||
int countByInsert = lev[i][j - 1] + 1;
|
|
||||||
int countByDel = lev[i - 1][j] + 1;
|
|
||||||
int countByReplace = lowerCaseSearchFilter.charAt(i - 1) == lowerCaseResult.charAt(j - 1) ? lev[i - 1][j - 1] : lev[i - 1][j - 1] + 1;
|
|
||||||
lev[i][j] = Math.min(countByInsert, Math.min(countByDel, countByReplace));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int diff = lev[lowerCaseSearchFilter.length()][lowerCaseResult.length()];
|
|
||||||
|
|
||||||
for (String s : StringUtils.tokenize(lowerCaseResult)) {
|
for (String s : StringUtils.tokenize(lowerCaseResult)) {
|
||||||
if (searchFilterWords.containsKey(s)) {
|
if (searchFilterWords.containsKey(s)) {
|
||||||
|
@ -357,29 +357,59 @@ public final class StringUtils {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DynamicCommonSubsequence {
|
public static class LevCalculator {
|
||||||
private LongestCommonSubsequence calculator;
|
private int[][] lev;
|
||||||
|
|
||||||
public DynamicCommonSubsequence(int intLengthA, int intLengthB) {
|
public LevCalculator() {
|
||||||
if (intLengthA > intLengthB) {
|
}
|
||||||
calculator = new LongestCommonSubsequence(intLengthA, intLengthB);
|
|
||||||
} else {
|
public LevCalculator(int length1, int length2) {
|
||||||
calculator = new LongestCommonSubsequence(intLengthB, intLengthA);
|
allocate(length1, length2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void allocate(int length1, int length2) {
|
||||||
|
length1 += 1;
|
||||||
|
length2 += 1;
|
||||||
|
lev = new int[length1][length2];
|
||||||
|
for (int i = 1; i < length1; i++) {
|
||||||
|
lev[i][0] = i;
|
||||||
|
}
|
||||||
|
int[] cache = lev[0];
|
||||||
|
for (int i = 0; i < length2; i++) {
|
||||||
|
cache[i] = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getLength1() {
|
||||||
|
return lev.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLength2() {
|
||||||
|
return lev[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int min(int a, int b, int c) {
|
||||||
|
return Math.min(a, Math.min(b, c));
|
||||||
|
}
|
||||||
|
|
||||||
public int calc(CharSequence a, CharSequence b) {
|
public int calc(CharSequence a, CharSequence b) {
|
||||||
if (a.length() < b.length()) {
|
if (lev == null || a.length() >= lev.length || b.length() >= lev[0].length) {
|
||||||
CharSequence t = a;
|
allocate(a.length(), b.length());
|
||||||
a = b;
|
|
||||||
b = t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculator.maxLengthA < a.length() || calculator.maxLengthB < b.length()) {
|
int lengthA = a.length() + 1, lengthB = b.length() + 1;
|
||||||
calculator = new LongestCommonSubsequence(a.length(), b.length());
|
|
||||||
|
for (int i = 1; i < lengthA; i++) {
|
||||||
|
for (int j = 1; j < lengthB; j++) {
|
||||||
|
lev[i][j] = min(
|
||||||
|
lev[i][j - 1] + 1, // insert
|
||||||
|
lev[i - 1][j] + 1, // del
|
||||||
|
a.charAt(i - 1) == b.charAt(j - 1) ? lev[i - 1][j - 1] : lev[i - 1][j - 1] + 1 // replace
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return calculator.calc(a, b);
|
return lev[a.length()][b.length()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user