Skip to content

Commit

Permalink
feat: search with pinyin
Browse files Browse the repository at this point in the history
add lib tinypinyin
  • Loading branch information
isHarryh committed Jan 20, 2025
1 parent 71b92fe commit a43d795
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 13 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,7 @@ project(":core") {
api "com.alibaba:fastjson:2.0.39"
// Log4j
api "apache-log4j:log4j:1.2.15"
// TiniPinyin
api 'com.github.promeg:tinypinyin:2.0.3'
}
}
34 changes: 34 additions & 0 deletions core/src/cn/harryh/arkpets/assets/ModelItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.github.promeg.pinyinhelper.Pinyin;

import java.io.File;
import java.io.Serializable;
Expand Down Expand Up @@ -42,7 +43,10 @@ public class ModelItem implements Serializable {
/** @deprecated Legacy field in old version dataset */ @JSONField @Deprecated
public JSONObject checksum;

// Lazy generated fields:
private ModelAssetAccessor accessor;
private String pinyinQuanpin;
private String pinyinSuoxie;

protected static final String[] extensions = {".atlas", ".png", ".skel"};

Expand All @@ -67,6 +71,36 @@ public ModelAssetAccessor getAccessor() {
return accessor;
}

/** Gets the 拼音全拼 (Pinyin Quanpin, full Pinyin transcription) of the model's name.
* @return A String.
*/
@JSONField(serialize = false)
public String getPinyinQuanpin() {
if (pinyinQuanpin == null)
pinyinQuanpin = Pinyin.toPinyin(name, "");
return pinyinQuanpin;
}

/** Gets the 拼音缩写 (Pinyin Suoxie, abbreviate Pinyin transcription) of the model's name.
* @return A String.
*/
@JSONField(serialize = false)
public String getPinyinSuoxie() {
if (pinyinSuoxie == null) {
String quanpin = Pinyin.toPinyin(name, " ");
if (!quanpin.trim().isEmpty()) {
StringBuilder builder = new StringBuilder();
for (String word : quanpin.split("\\s+")) {
builder.append(word.charAt(0));
}
pinyinSuoxie = builder.toString();
} else {
pinyinSuoxie = "";
}
}
return pinyinSuoxie;
}

/** Verifies the integrity of the necessary fields of this {@code ModelItem}.
* @return {@code true} if all the following conditions are satisfied, otherwise {@code false}:
* 1. Both {@code assetDir} and {@code type} are not {@code null}.
Expand Down
60 changes: 49 additions & 11 deletions core/src/cn/harryh/arkpets/assets/ModelItemGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,23 +45,61 @@ public ModelItemGroup() {
public ModelItemGroup searchByKeyWords(String keyWords) {
if (keyWords == null || keyWords.isEmpty())
return this;
String[] wordList = keyWords.split(" ");
String[] wordList = keyWords.toUpperCase().split(" ");
ModelItemGroup result = new ModelItemGroup();
for (ModelItem asset : this) {
for (String word : wordList) {
if (asset.name != null &&
asset.name.toLowerCase().contains(word.toLowerCase())) {
result.add(asset);

// Rule: match name
for (ModelItem model : this) {
if (!result.contains(model) && model.name != null) {
String nameLower = model.name.toUpperCase();
for (String word : wordList) {
if (nameLower.contains(word)) {
result.add(model);
break;
}
}
}
}

// Rule: match appellation
for (ModelItem model : this) {
if (!result.contains(model) && model.appellation != null) {
String appellLower = model.appellation.toUpperCase();
for (String word : wordList) {
if (appellLower.contains(word)) {
result.add(model);
break;
}
}
}
}

// Rule: match Pinyin suoxie
for (ModelItem model : this) {
if (!result.contains(model) && model.getPinyinSuoxie() != null) {
String appellLower = model.getPinyinSuoxie().toUpperCase();
for (String word : wordList) {
if (appellLower.contains(word)) {
result.add(model);
break;
}
}
}
for (String word : wordList) {
if (asset.appellation != null &&
asset.appellation.toLowerCase().contains(word.toLowerCase())) {
if (!result.contains(asset))
result.add(asset);
}

// Rule: match Pinyin quanpin
for (ModelItem model : this) {
if (!result.contains(model) && model.getPinyinQuanpin() != null) {
String appellLower = model.getPinyinQuanpin().toUpperCase();
for (String word : wordList) {
if (appellLower.contains(word)) {
result.add(model);
break;
}
}
}
}

return result;
}

Expand Down
8 changes: 6 additions & 2 deletions desktop/src/cn/harryh/arkpets/controllers/ModelsModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -447,21 +447,25 @@ public void modelSearch(String keyWords) {
searchModelView.getItems().clear();
searchModelStatus.setText("");
if (assertModelLoaded(false)) {
// Filter and search assets
// Filter assets
int rawSize = assetItemList.size();
ModelItemGroup favoured = !filterFavorite ? assetItemList :
assetItemList.filter(ModelItem.PropertyExtractor.ASSET_ITEM_KEY, app.config.character_favorites.keySet(), ModelItemGroup.FilterMode.MATCH_ANY);
ModelItemGroup filtered = filterTagSet.isEmpty() ? favoured :
favoured.filter(ModelItem.PropertyExtractor.ASSET_ITEM_SORT_TAGS, filterTagSet);
// Search assets
long tStart = System.nanoTime();
ModelItemGroup searched = filtered.searchByKeyWords(keyWords);
long tEnd = System.nanoTime();
int curSize = searched.size();
searchModelStatus.setText((rawSize == curSize ? rawSize : curSize + " / " + rawSize) + " 个模型");
// Add cells
for (JFXListCell<ModelItem> cell : modelCellList)
if (searched.contains(cell.getItem()))
searchModelView.getItems().add(cell);
Logger.info("ModelManager", "Search \"%s\" (%d results, %.1f ms)"
.formatted(keyWords, curSize, (tEnd - tStart) / 1000000f));
}
Logger.info("ModelManager", "Search \"" + keyWords + "\" (" + searchModelView.getItems().size() + ")");
searchModelView.refresh();
}

Expand Down

0 comments on commit a43d795

Please sign in to comment.