diff --git a/TaigiDict/app/build.gradle b/TaigiDict/app/build.gradle index a9a7998..e81cd82 100644 --- a/TaigiDict/app/build.gradle +++ b/TaigiDict/app/build.gradle @@ -24,8 +24,8 @@ android { applicationId "com.taccotap.taigidict" minSdkVersion 16 targetSdkVersion 25 - versionCode 1 - versionName "1.0.0" + versionCode 2 + versionName "1.0.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } @@ -49,6 +49,12 @@ android { output.outputFile = new File(output.outputFile.parent, newName) } } + + buildConfigField "boolean", "DEBUG_LOG", "false" + } + + debug { + buildConfigField "boolean", "DEBUG_LOG", "true" } } } diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchActivity.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchActivity.java index c9ba6a0..70f03a0 100644 --- a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchActivity.java +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchActivity.java @@ -7,14 +7,18 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.text.TextUtils; +import android.util.Log; import android.view.View; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.RadioGroup; +import com.taccotap.taigidict.BuildConfig; import com.taccotap.taigidict.R; import com.taccotap.taigidict.tailo.utils.TailoConstants; import com.taccotap.taigidict.tailo.word.TailoWordActivity; +import com.taccotap.taigidict.utils.LomajiUnicodeUtils; +import com.taccotap.taigidict.utils.Poj2TailoUtils; import com.taccotap.taigidictmodel.tailo.TlTaigiWord; import butterknife.BindView; @@ -23,6 +27,7 @@ import io.realm.Realm; public class TailoSearchActivity extends AppCompatActivity implements SearchView.OnQueryTextListener, CompoundButton.OnCheckedChangeListener { + private static final String TAG = TailoSearchActivity.class.getSimpleName(); public static final String ACTION_SEARCH_LMJ = "ACTION_SEARCH_LMJ"; public static final String ACTION_SEARCH_HOAGI = "ACTION_SEARCH_HOAGI"; @@ -132,8 +137,6 @@ private void doSearch(String query) { private void doSearch(String query, boolean isSearchEquals) { mCurrentQueryString = query; - query = query.trim(); - if (TextUtils.isEmpty(query)) { query = TailoConstants.DEFAULT_QUERY_STRING; } @@ -164,11 +167,36 @@ public boolean onQueryTextSubmit(String query) { } @Override - public boolean onQueryTextChange(String newText) { - doSearch(newText); + public boolean onQueryTextChange(String query) { + String handledQueryString = query.trim(); + + if (mCurrentSearchType == SEARCH_TYPE_LOMAJI) { + String fixedLomaji = LomajiUnicodeUtils.fixTwoCharWord(query); + + if (BuildConfig.DEBUG_LOG) { + logInputUnicode(fixedLomaji); + } + + handledQueryString = Poj2TailoUtils.poj2tailo(fixedLomaji); + } + + doSearch(handledQueryString); + return true; } + private void logInputUnicode(String query) { + int count = query.length(); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < count; i++) { + final char c = query.charAt(i); + String stringUnicode = Integer.toHexString((int) c); + stringBuilder.append(stringUnicode + " "); + } + + Log.d(TAG, "Input: " + query + ", Unicode: " + stringBuilder.toString()); + } + @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { if (compoundButton == mSearchContainsRadioButton && checked) { diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchAdapter.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchAdapter.java index d85721e..3c29c97 100644 --- a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchAdapter.java +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/search/TailoSearchAdapter.java @@ -114,6 +114,8 @@ public void searchAll(String query) { RealmQuery where = mRealm.where(TlTaigiWord.class); where = where.contains("lomaji", query, Case.INSENSITIVE) + .or().contains("hanji", query, Case.INSENSITIVE) + .or().contains("hoagiWords.hoagiWord", query) .or().contains("descriptions.description", query) .or().contains("descriptions.exampleSentences.exampleSentenceHanji", query) .or().contains("descriptions.exampleSentences.exampleSentenceLomaji", query) diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoConstants.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoConstants.java index 50900da..3dd288e 100644 --- a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoConstants.java +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoConstants.java @@ -2,6 +2,11 @@ public class TailoConstants { public static final String URL_AUDIO_FILE_PREFIX = "http://twblg.dict.edu.tw/holodict_new/audio/"; + + // example: http://twblg.dict.edu.tw/holodict_new/audio/fulu_wailaici/gl1.mp3 + // start from mainCode 31001 + public static final String URL_NODE_WAILAI = "fulu_wailaici/gl"; + public static final String URL_AUDIO_FILE_POSTFIX = ".mp3"; public static final String DEFAULT_QUERY_STRING = "Tâi-gí"; diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoTaigiWordAudioUrlHelper.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoTaigiWordAudioUrlHelper.java index 0e2ee26..f1d111e 100644 --- a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoTaigiWordAudioUrlHelper.java +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/utils/TailoTaigiWordAudioUrlHelper.java @@ -16,4 +16,17 @@ public static String getTaigiAudioUrl(int mainCode) { return stringBuilder.toString(); } + + public static String getTaigiWailaiAudioUrl(int mainCode) { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append(TailoConstants.URL_AUDIO_FILE_PREFIX + TailoConstants.URL_NODE_WAILAI); + + String leadingZeroMainCodeString = String.format(Locale.ENGLISH, "%d", mainCode - 31000); + stringBuilder.append(leadingZeroMainCodeString); + + stringBuilder.append(TailoConstants.URL_AUDIO_FILE_POSTFIX); + + return stringBuilder.toString(); + } } diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/word/TailoWordActivity.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/word/TailoWordActivity.java index 079aaad..ea7a34f 100644 --- a/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/word/TailoWordActivity.java +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/tailo/word/TailoWordActivity.java @@ -52,6 +52,8 @@ public class TailoWordActivity extends AppCompatActivity { private Realm mRealm; private ActivityTailoWordBinding mBinding; private MediaPlayer mMediaPlayer; + private TlTaigiWord mTaigiWord; + private String mVoiceUrl; @Override protected void onCreate(Bundle savedInstanceState) { @@ -80,22 +82,28 @@ private void handleCurrentWord() { mRealm = Realm.getDefaultInstance(); // bind word, description - final TlTaigiWord taigiWord = mRealm.where(TlTaigiWord.class).equalTo("mainCode", mMainCode).findFirstAsync(); - taigiWord.addChangeListener(new RealmChangeListener() { + mTaigiWord = mRealm.where(TlTaigiWord.class).equalTo("mainCode", mMainCode).findFirstAsync(); + mTaigiWord.addChangeListener(new RealmChangeListener() { @Override public void onChange(RealmModel element) { - Log.i(TAG, "lomaji=" + taigiWord.getLomaji()); + Log.i(TAG, "lomaji=" + mTaigiWord.getLomaji()); // bind word - mBinding.setTaigiWord(taigiWord); + mBinding.setTaigiWord(mTaigiWord); - // check voice avalibility (附錄皆無語音檔) - if (taigiWord.getWordPropertyCode() >= 11 && taigiWord.getWordPropertyCode() <= 22) { + if (mTaigiWord.getWordPropertyCode() == 12) { + mVoiceUrl = TailoTaigiWordAudioUrlHelper.getTaigiWailaiAudioUrl(mMainCode); + } else { + mVoiceUrl = TailoTaigiWordAudioUrlHelper.getTaigiAudioUrl(mMainCode); + } + + // check voice avalibility (附錄(11~22)除了外來語(12),皆無語音檔) + if (mTaigiWord.getWordPropertyCode() >= 11 && mTaigiWord.getWordPropertyCode() <= 22 && mTaigiWord.getWordPropertyCode() != 12) { mFloatingActionButton.setVisibility(View.GONE); } // bind desc - final RealmList descriptions = taigiWord.getDescriptions(); + final RealmList descriptions = mTaigiWord.getDescriptions(); final int descriptionsCount = descriptions.size(); if (descriptionsCount > 0) { StringBuilder stringBuilder = new StringBuilder(); @@ -152,7 +160,7 @@ public void onChange(RealmModel element) { } // bind word property - final int wordPropertyCode = taigiWord.getWordPropertyCode(); + final int wordPropertyCode = mTaigiWord.getWordPropertyCode(); if (wordPropertyCode <= 2) { mWordPropertyLayout.setVisibility(View.GONE); } @@ -166,7 +174,12 @@ void onClickFab() { Toast.makeText(TailoWordActivity.this, R.string.toast_voice_need_network_connection, Toast.LENGTH_SHORT).show(); return; } - String voiceUrl = TailoTaigiWordAudioUrlHelper.getTaigiAudioUrl(mMainCode); + + if (mVoiceUrl == null) { + // TODO handle data state + Log.e(TAG, "Data not ready yet."); + return; + } if (mMediaPlayer == null) { mMediaPlayer = new MediaPlayer(); @@ -194,7 +207,7 @@ public void onPrepared(MediaPlayer mediaPlayer) { }); try { - mMediaPlayer.setDataSource(this, Uri.parse(voiceUrl)); + mMediaPlayer.setDataSource(this, Uri.parse(mVoiceUrl)); mMediaPlayer.prepareAsync(); } catch (Exception e) { e.printStackTrace(); diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/LomajiUnicodeUtils.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/LomajiUnicodeUtils.java new file mode 100644 index 0000000..8ddce86 --- /dev/null +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/LomajiUnicodeUtils.java @@ -0,0 +1,79 @@ +package com.taccotap.taigidict.utils; + +public class LomajiUnicodeUtils { + + // fix two-char word to one-char word + public static String fixTwoCharWord(String unicodeLomaji) { + String fixed = unicodeLomaji + // x8 not change + + // a + .replaceAll("\u0061\u0301", "\u00e1") // a2 + .replaceAll("\u0061\u0300", "\u00e0") // a3 + .replaceAll("\u0061\u0302", "\u00e2") // a5 + .replaceAll("\u0061\u0304", "\u0101") // a7 + + .replaceAll("\u0041\u0301", "\u00c1") // A2 + .replaceAll("\u0041\u0300", "\u00c0") // A3 + .replaceAll("\u0041\u0302", "\u00c2") // A5 + .replaceAll("\u0041\u0304", "\u0100") // A7 + + // i + .replaceAll("\u0069\u0301", "\u00ed") // i2 + .replaceAll("\u0069\u0300", "\u00ec") // i3 + .replaceAll("\u0069\u0302", "\u00ee") // i5 + .replaceAll("\u0069\u0304", "\u012b") // i7 + + .replaceAll("\u0049\u0301", "\u00cd") // I2 + .replaceAll("\u0049\u0300", "\u00cc") // I3 + .replaceAll("\u0049\u0302", "\u00ce") // I5 + .replaceAll("\u0049\u0304", "\u012a") // I7 + + // u + .replaceAll("\u0075\u0301", "\u00fa") // u2 + .replaceAll("\u0075\u0300", "\u00f9") // u3 + .replaceAll("\u0075\u0302", "\u00fb") // u5 + .replaceAll("\u0075\u0304", "\u016b") // u7 + + .replaceAll("\u0055\u0301", "\u00da") // U2 + .replaceAll("\u0055\u0300", "\u00d9") // U3 + .replaceAll("\u0055\u0302", "\u00db") // U5 + .replaceAll("\u0055\u0304", "\u016a") // U7 + + // e + .replaceAll("\u0065\u0301", "\u00e9") // e2 + .replaceAll("\u0065\u0300", "\u00e8") // e3 + .replaceAll("\u0065\u0302", "\u00ea") // e5 + .replaceAll("\u0065\u0304", "\u0113") // e7 + + .replaceAll("\u0045\u0301", "\u00c9") // E2 + .replaceAll("\u0045\u0300", "\u00c8") // E3 + .replaceAll("\u0045\u0302", "\u00ca") // E5 + .replaceAll("\u0045\u0304", "\u0102") // E7 + + // o + .replaceAll("\u006f\u0301", "\u00f3") // o2 + .replaceAll("\u006f\u0300", "\u00f2") // o3 + .replaceAll("\u006f\u0302", "\u00f4") // o5 + .replaceAll("\u006f\u0304", "\u014d") // o7 + + .replaceAll("\u004f\u0301", "\u00d3") // O2 + .replaceAll("\u004f\u0300", "\u00d2") // O3 + .replaceAll("\u004f\u0302", "\u00d4") // O5 + .replaceAll("\u004f\u0304", "\u014c") // O7 + + // n + .replaceAll("\u006e\u0301", "\u0144") // n2 + .replaceAll("\u006e\u0300", "\u01f9") // n3; n5, n7 not change + + .replaceAll("\u004e\u0301", "\u0143") // N2 + .replaceAll("\u004e\u0300", "\u01f8") // N3; N5, N7 not change + + // m + .replaceAll("\u006d\u0301", "\u1e3f") // m2; m3, m5, m7 not change + + .replaceAll("\u004d\u0301", "\u1e3e"); // M2; M3, M5, M7 not change + + return fixed; + } +} diff --git a/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/Poj2TailoUtils.java b/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/Poj2TailoUtils.java new file mode 100644 index 0000000..9541236 --- /dev/null +++ b/TaigiDict/app/src/main/java/com/taccotap/taigidict/utils/Poj2TailoUtils.java @@ -0,0 +1,23 @@ +package com.taccotap.taigidict.utils; + +public class Poj2TailoUtils { + + public static final String poj2tailo(String poj) { + String tailo = poj.replaceAll("ch", "ts") // ch -> ts + .replaceAll("Ch", "Ts") // Ch -> Ts + .replaceAll("\u207f", "nn") // ⁿ -> nn + .replaceAll("o(.?)\u0358", "o$1o") // o͘ -> oo, ó͘ -> óo, and etc. + .replaceAll("O(.?)\u0358", "O$1o") // o͘ -> oo, ó͘ -> óo, and etc. + .replaceAll("o([aáàâāa̍AÁÀÂĀA̍eéèêēe̍EÉÈÊĒE̍])", "u$1") // oa -> ua, oe -> ue, and etc. + .replaceAll("O([aáàâāa̍AÁÀÂĀA̍eéèêēe̍EÉÈÊĒE̍])", "U$1") // Oa -> Ua, Oe -> Ue, and etc. + .replaceAll("ek", "ik") // ek -> ik + .replaceAll("Ek", "Ik") // Ek -> Ik + .replaceAll("e\u030dk", "i\u030dk") // e̍k -> i̍k + .replaceAll("E\u030dk", "I\u030dk") // E̍k -> I̍k + .replaceAll("eng", "ing") // eng -> ing + .replaceAll("Eng", "Ing") // Eng -> Ing + .replaceAll("e\u030dng", "i\u030dng") // e̍ng -> i̍ng + .replaceAll("E\u030dng", "I\u030dng"); // E̍ng -> I̍ng + return tailo; + } +} diff --git a/TaigiDict/taigi_dict_parser_app/build.gradle b/TaigiDict/taigi_dict_parser_app/build.gradle index d8f0a0d..02aa8cb 100644 --- a/TaigiDict/taigi_dict_parser_app/build.gradle +++ b/TaigiDict/taigi_dict_parser_app/build.gradle @@ -9,7 +9,7 @@ android { minSdkVersion 16 targetSdkVersion 25 versionCode 1 - versionName "1.0" + versionName "1.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } diff --git "a/TaigiDict/taigi_dict_parser_app/src/main/assets/tailo/\350\251\236\347\233\256\347\270\275\346\252\224(\345\220\253\344\277\227\350\253\272).xls" "b/TaigiDict/taigi_dict_parser_app/src/main/assets/tailo/\350\251\236\347\233\256\347\270\275\346\252\224(\345\220\253\344\277\227\350\253\272).xls" index fecd058..ccc7a0d 100644 Binary files "a/TaigiDict/taigi_dict_parser_app/src/main/assets/tailo/\350\251\236\347\233\256\347\270\275\346\252\224(\345\220\253\344\277\227\350\253\272).xls" and "b/TaigiDict/taigi_dict_parser_app/src/main/assets/tailo/\350\251\236\347\233\256\347\270\275\346\252\224(\345\220\253\344\277\227\350\253\272).xls" differ diff --git a/TaigiDict/taigi_dict_realm_model/build.gradle b/TaigiDict/taigi_dict_realm_model/build.gradle index afcc332..4464687 100644 --- a/TaigiDict/taigi_dict_realm_model/build.gradle +++ b/TaigiDict/taigi_dict_realm_model/build.gradle @@ -9,7 +9,7 @@ android { minSdkVersion 16 targetSdkVersion 25 versionCode 1 - versionName "1.0" + versionName "1.0.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"