Exemplo n.º 1
0
        /// <summary>
        /// Attempts to retrieve the kanji strokes SVG matching the given kanji inside the zip file.
        /// </summary>
        /// <param name="k">Target kanji.</param>
        /// <returns>A kanji strokes entity, never null, that contains either the retrieved data or an
        /// empty byte array when the entry was not found.</returns>
        private KanjiStrokes RetrieveSvg(KanjiEntity k)
        {
            KanjiStrokes strokes = new KanjiStrokes();

            strokes.FramesSvg = new byte[0];

            if (!k.UnicodeValue.HasValue)
            {
                return(strokes);
            }

            ZipArchive      svgZip    = GetSvgZipArchive();
            string          entryName = string.Format("{0}_frames.svg", k.UnicodeValue.Value);
            ZipArchiveEntry entry     = svgZip.GetEntry(entryName);

            if (entry != null)
            {
                using (Stream stream = entry.Open())
                {
                    strokes.FramesSvg = StringCompressionHelper.Zip(StreamHelper.ReadToEnd(stream));
                    StringCompressionHelper.Unzip(strokes.FramesSvg);
                }
            }

            return(strokes);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Gets all kanji with minimal info.
        /// </summary>
        /// <returns>All kanji with minimal info.</returns>
        public IEnumerable <KanjiEntity> GetAllKanji()
        {
            DaoConnection connection = null;

            try
            {
                // Create and open synchronously the primary Kanji connection.
                connection = DaoConnection.Open(DaoConnectionEnum.KanjiDatabase);

                IEnumerable <NameValueCollection> results = connection.Query(
                    string.Format("SELECT * FROM {0}", SqlHelper.Table_Kanji));

                KanjiBuilder kanjiBuilder = new KanjiBuilder();
                foreach (NameValueCollection nvcKanji in results)
                {
                    KanjiEntity kanji = kanjiBuilder.BuildEntity(nvcKanji, null);
                    yield return(kanji);
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Loads properties from the given kanji entity.
        /// </summary>
        /// <param name="se">Target SRS entry.</param>
        /// <param name="k">Kanji to load.</param>
        public static void LoadFromKanji(this SrsEntry se, KanjiEntity k)
        {
            // Compute the meaning string.
            string meaningString = string.Empty;

            foreach (KanjiMeaning km in k.Meanings)
            {
                meaningString += MultiValueFieldHelper.ReplaceSeparator(km.Meaning) + MultiValueFieldHelper.ValueSeparator;
            }
            meaningString = meaningString.Trim(
                new char[] { MultiValueFieldHelper.ValueSeparator });
            meaningString = MultiValueFieldHelper.Expand(meaningString);

            // Compute the reading string.
            string readingString = (k.OnYomi
                                    + MultiValueFieldHelper.ValueSeparator)
                                   + k.KunYomi;

            readingString = MultiValueFieldHelper.Expand(readingString
                                                         .Trim(new char[] { MultiValueFieldHelper.ValueSeparator }));

            // Set values.
            se.Meanings        = meaningString;
            se.Readings        = readingString;
            se.AssociatedKanji = k.Character;
        }
Exemplo n.º 4
0
 public VocabFilter()
 {
     Kanji               = new KanjiEntity[0] {
     };
     IsCommonFirst       = true;
     IsShortReadingFirst = true;
     JlptLevel           = Levels.IgnoreJlptLevel;
 }
Exemplo n.º 5
0
        /// <summary>
        /// Retrieves and returns the collection of vocab matching the
        /// given filters.
        /// </summary>
        /// <param name="kanji">Kanji filter. Only vocab containing this
        /// kanji will be filtered in.</param>
        /// <param name="readingFilter">Reading filter. Only vocab containing
        /// this string in their kana or kanji reading will be filtered in.</param>
        /// <param name="meaningFilter">Meaning filter. Only vocab containing
        /// this string as part of at least one of their meaning entries will
        /// be filtered in.</param>
        /// <param name="categoryFilter">If not null, this category is used as the filter.</param>
        /// <param name="jlptLevel">The JLPT level to filter
        /// (1-5, where a lower value means it is not covered on the JLPT
        /// and a higher value means that this filter will be ignored).</param>
        /// <param name="wkLevel">The WaniKani level to filter
        /// (1-60, where a higher value means it is not taught by WaniKani
        /// and a lower value means that this filter will be ignored).</param>
        /// <param name="isCommonFirst">Indicates if common vocab should be
        /// presented first. If false, results are sorted only by the length
        /// of their writing (asc or desc depending on the parameter)</param>
        /// <param name="isShortWritingFirst">Indicates if results should
        /// be sorted by ascending or descending writing length.
        /// If True, short readings come first. If False, long readings
        /// come first.</param>
        /// <returns>Vocab entities matching the filters.</returns>
        public IEnumerable <VocabEntity> GetFilteredVocab(KanjiEntity kanji,
                                                          string readingFilter, string meaningFilter, VocabCategory categoryFilter,
                                                          int jlptLevel, int wkLevel,
                                                          bool isCommonFirst, bool isShortWritingFirst)
        {
            List <DaoParameter> parameters = new List <DaoParameter>();
            string sqlFilterClauses        = BuildVocabFilterClauses(parameters, kanji,
                                                                     readingFilter, meaningFilter, categoryFilter, jlptLevel, wkLevel);

            string sortClause = "ORDER BY ";

            if (isCommonFirst)
            {
                sortClause += string.Format("v.{0} DESC,", SqlHelper.Field_Vocab_IsCommon);
            }
            sortClause += string.Format("length(v.{0}) {1}",
                                        SqlHelper.Field_Vocab_KanaWriting,
                                        (isShortWritingFirst ? "ASC" : "DESC"));

            DaoConnection connection    = null;
            DaoConnection srsConnection = null;

            try
            {
                connection    = DaoConnection.Open(DaoConnectionEnum.KanjiDatabase);
                srsConnection = new DaoConnection(DaoConnectionEnum.SrsDatabase);
                srsConnection.OpenAsync();

                IEnumerable <NameValueCollection> vocabs = connection.Query(
                    string.Format("SELECT DISTINCT v.* FROM {0} v {1}{2}",
                                  SqlHelper.Table_Vocab,
                                  sqlFilterClauses,
                                  sortClause),
                    parameters.ToArray());

                VocabBuilder vocabBuilder = new VocabBuilder();
                foreach (NameValueCollection nvcVocab in vocabs)
                {
                    VocabEntity vocab = vocabBuilder.BuildEntity(nvcVocab, null);
                    IncludeCategories(connection, vocab);
                    IncludeMeanings(connection, vocab);
                    IncludeKanji(connection, srsConnection, vocab);
                    IncludeSrsEntries(srsConnection, vocab);
                    IncludeVariants(connection, vocab);
                    yield return(vocab);
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets a set of kanji matching the given filters.
        /// </summary>
        /// <param name="radicals">Filters out kanji which do not contain all
        /// of the contained radicals.</param>
        /// <param name="textFilter">If set, filters out all kanji that are not
        /// contained in the string.</param>
        /// <param name="meaningFilter">Filter for the meaning of the kanji.</param>
        /// <param name="anyReadingFilter">Filter matching any reading of the kanji.
        /// <remarks>If set, this parameter will override the three reading filters.
        /// </remarks></param>
        /// <param name="onYomiFilter">Filter for the on'yomi reading of the kanji.
        /// <remarks>This parameter will be ignored if
        /// <paramref name="anyReadingFilter"/> is set.</remarks></param>
        /// <param name="kunYomiFilter">Filter for the kun'yomi reading of the kanji.
        /// <remarks>This parameter will be ignored if
        /// <paramref name="anyReadingFilter"/> is set.</remarks></param>
        /// <param name="nanoriFilter">Filter for the nanori reading of the kanji.
        /// <remarks>This parameter will be ignored if
        /// <paramref name="anyReadingFilter"/> is set.</remarks></param>
        /// <returns>Kanji matching the given filters.</returns>
        public IEnumerable <KanjiEntity> GetFilteredKanji(RadicalGroup[] radicals, string textFilter,
                                                          string meaningFilter, string anyReadingFilter, string onYomiFilter, string kunYomiFilter,
                                                          string nanoriFilter, int jlptLevel, int wkLevel)
        {
            List <DaoParameter> parameters = new List <DaoParameter>();
            string sqlFilter = BuildKanjiFilterClauses(parameters, radicals, textFilter,
                                                       meaningFilter, anyReadingFilter, onYomiFilter, kunYomiFilter, nanoriFilter,
                                                       jlptLevel, wkLevel);

            DaoConnection connection    = null;
            DaoConnection srsConnection = null;

            try
            {
                // Create and open synchronously the primary Kanji connection.
                connection = DaoConnection.Open(DaoConnectionEnum.KanjiDatabase);

                // Create the secondary Srs connection and open it asynchronously.
                srsConnection = new DaoConnection(DaoConnectionEnum.SrsDatabase);
                srsConnection.OpenAsync();

                // FILTERS COMPUTED.
                // Execute the final request.
                IEnumerable <NameValueCollection> results = connection.Query(string.Format(
                                                                                 "SELECT * FROM {0} k {1}ORDER BY (k.{2} IS NULL),(k.{2});",
                                                                                 SqlHelper.Table_Kanji,
                                                                                 sqlFilter,
                                                                                 SqlHelper.Field_Kanji_MostUsedRank),
                                                                             parameters.ToArray());

                KanjiBuilder kanjiBuilder = new KanjiBuilder();
                foreach (NameValueCollection nvcKanji in results)
                {
                    KanjiEntity kanji = kanjiBuilder.BuildEntity(nvcKanji, null);
                    IncludeKanjiMeanings(connection, kanji);
                    IncludeRadicals(connection, kanji);
                    IncludeSrsEntries(srsConnection, kanji);
                    yield return(kanji);
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
                if (srsConnection != null)
                {
                    srsConnection.Dispose();
                }
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Retrieves and includes the SRS entries matching the given kanji and includes
        /// them in the entity.
        /// </summary>
        internal static void IncludeSrsEntries(DaoConnection connection, KanjiEntity kanji)
        {
            IEnumerable <NameValueCollection> nvcEntries = connection.Query(
                string.Format("SELECT * FROM {0} srs WHERE srs.{1}=@k",
                              SqlHelper.Table_SrsEntry,
                              SqlHelper.Field_SrsEntry_AssociatedKanji),
                new DaoParameter("@k", kanji.Character));

            SrsEntryBuilder srsEntryBuilder = new SrsEntryBuilder();

            foreach (NameValueCollection nvcEntry in nvcEntries)
            {
                kanji.SrsEntries.Add(srsEntryBuilder.BuildEntity(nvcEntry, null));
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// See <see cref="Kanji.Database.Dao.VocabDao.GetFilteredVocab"/>.
        /// Returns the results count.
        /// </summary>
        public long GetFilteredVocabCount(KanjiEntity kanji,
                                          string readingFilter, string meaningFilter, VocabCategory categoryFilter, int jlptLevel, int wkLevel)
        {
            List <DaoParameter> parameters = new List <DaoParameter>();
            string sqlFilterClauses        = BuildVocabFilterClauses(parameters, kanji,
                                                                     readingFilter, meaningFilter, categoryFilter, jlptLevel, wkLevel);

            using (DaoConnection connection
                       = DaoConnection.Open(DaoConnectionEnum.KanjiDatabase))
            {
                return((long)connection.QueryScalar(
                           string.Format("SELECT count(1) FROM {0} v {1}",
                                         SqlHelper.Table_Vocab,
                                         sqlFilterClauses),
                           parameters.ToArray()));
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Retrieves and includes the meanings of the given kanji in the entity.
        /// </summary>
        internal static void IncludeKanjiMeanings(DaoConnection connection, KanjiEntity kanji)
        {
            IEnumerable <NameValueCollection> nvcMeanings = connection.Query(
                string.Format("SELECT * FROM {0} km WHERE km.{1}=@kanjiId AND km.{2} IS NULL;",
                              SqlHelper.Table_KanjiMeaning,
                              SqlHelper.Field_KanjiMeaning_KanjiId,
                              SqlHelper.Field_KanjiMeaning_Language),
                new DaoParameter("@kanjiId", kanji.ID));

            KanjiMeaningBuilder meaningBuilder = new KanjiMeaningBuilder();

            foreach (NameValueCollection nvcMeaning in nvcMeanings)
            {
                // For each meaning result : build a meaning and set the associations.
                KanjiMeaning meaning = meaningBuilder.BuildEntity(nvcMeaning, null);
                meaning.Kanji = kanji;
                kanji.Meanings.Add(meaning);
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Retrieves and includes kanji entities in the given radical entity.
        /// </summary>
        private void IncludeKanji(DaoConnection connection, RadicalEntity radical)
        {
            IEnumerable <NameValueCollection> results = connection.Query(
                string.Format(
                    "SELECT kr.{0} {1} FROM {2} kr WHERE kr.{3}=@rid",
                    SqlHelper.Field_Kanji_Radical_KanjiId,
                    SqlHelper.Field_Kanji_Id,
                    SqlHelper.Table_Kanji_Radical,
                    SqlHelper.Field_Kanji_Radical_RadicalId),
                new DaoParameter("@rid", radical.ID));

            KanjiBuilder kanjiBuilder = new KanjiBuilder();

            foreach (NameValueCollection nvcKanjiRadical in results)
            {
                KanjiEntity kanji = kanjiBuilder.BuildEntity(nvcKanjiRadical, null);
                radical.Kanji.Add(kanji);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Retrieves and includes the radicals of the given kanji in the entity.
        /// </summary>
        internal static void IncludeRadicals(DaoConnection connection, KanjiEntity kanji)
        {
            IEnumerable <NameValueCollection> nvcRadicals = connection.Query(
                string.Format("SELECT * FROM {0} r JOIN {1} kr ON (kr.{2}=r.{3}) WHERE kr.{4}=@kanjiId;",
                              SqlHelper.Table_Radical,
                              SqlHelper.Table_Kanji_Radical,
                              SqlHelper.Field_Kanji_Radical_RadicalId,
                              SqlHelper.Field_Radical_Id,
                              SqlHelper.Field_Kanji_Radical_KanjiId),
                new DaoParameter("@kanjiId", kanji.ID));

            RadicalBuilder radicalBuilder = new RadicalBuilder();

            foreach (NameValueCollection nvcRadical in nvcRadicals)
            {
                // For each meaning result : build a radical and set the associations.
                RadicalEntity radical = radicalBuilder.BuildEntity(nvcRadical, null);
                kanji.Radicals.Add(radical);
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Includes the kanji of the given vocab in the entity.
        /// </summary>
        private void IncludeKanji(DaoConnection connection, DaoConnection srsConnection,
                                  VocabEntity vocab)
        {
            IEnumerable <NameValueCollection> results = connection.Query(
                string.Format("SELECT k.* FROM {0} kv JOIN {1} k ON (k.{2}=kv.{3}) WHERE kv.{4}=@vid",
                              SqlHelper.Table_Kanji_Vocab,
                              SqlHelper.Table_Kanji,
                              SqlHelper.Field_Kanji_Id,
                              SqlHelper.Field_Kanji_Vocab_KanjiId,
                              SqlHelper.Field_Kanji_Vocab_VocabId),
                new DaoParameter("@vid", vocab.ID));

            KanjiBuilder kanjiBuilder = new KanjiBuilder();

            foreach (NameValueCollection nvcKanji in results)
            {
                KanjiEntity kanji = kanjiBuilder.BuildEntity(nvcKanji, null);
                KanjiDao.IncludeKanjiMeanings(connection, kanji);
                KanjiDao.IncludeRadicals(connection, kanji);
                KanjiDao.IncludeSrsEntries(srsConnection, kanji);
                vocab.Kanji.Add(kanji);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Gets the first kanji that matches the given character.
        /// </summary>
        /// <param name="character">Character to match.</param>
        /// <returns>First kanji matching the given character.
        /// Null if nothing was found.</returns>
        public KanjiEntity GetFirstMatchingKanji(string character)
        {
            KanjiEntity result = null;

            DaoConnection connection = null;

            try
            {
                // Create and open synchronously the primary Kanji connection.
                connection = DaoConnection.Open(DaoConnectionEnum.KanjiDatabase);

                // FILTERS COMPUTED.
                // Execute the final request.
                IEnumerable <NameValueCollection> results = connection.Query(string.Format(
                                                                                 "SELECT * FROM {0} k WHERE k.{1}=@k ORDER BY (k.{2} IS NULL),(k.{2});",
                                                                                 SqlHelper.Table_Kanji,
                                                                                 SqlHelper.Field_Kanji_Character,
                                                                                 SqlHelper.Field_Kanji_MostUsedRank),
                                                                             new DaoParameter("@k", character));

                if (results.Any())
                {
                    result = new KanjiBuilder()
                             .BuildEntity(results.First(), null);
                    IncludeKanjiMeanings(connection, result);
                }
            }
            finally
            {
                if (connection != null)
                {
                    connection.Dispose();
                }
            }

            return(result);
        }
Exemplo n.º 14
0
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null)
            {
                return(null);
            }

            if (value is KanjiEntity && parameter is KanjiToStringConversionType)
            {
                KanjiEntity kanji = ((KanjiEntity)value);
                KanjiToStringConversionType conversionType = (KanjiToStringConversionType)parameter;

                KanjiMeaning[] meanings = kanji.Meanings.ToArray();

                if (meanings.Any())
                {
                    if (conversionType == KanjiToStringConversionType.Short)
                    {
                        // Short conversion
                        // Take the first meaning
                        KanjiMeaning meaning = meanings.First();
                        if (!string.IsNullOrEmpty(meaning.Meaning))
                        {
                            // Capitalize the first letter
                            string capitalizedFirstLetter = meaning.Meaning.Substring(0, 1).ToUpper();
                            string meaningString          = capitalizedFirstLetter + meaning.Meaning.Substring(1);

                            // Shorten the result if too long
                            if (meaningString.Length > MaxStringLength)
                            {
                                meaningString = meaningString.Substring(0, MaxStringLength) + "[...]";
                            }

                            // Return the formatted first meaning
                            return(meaningString);
                        }
                    }
                    else
                    {
                        // Full conversion
                        // Build a string containing each meaning separated by a comma.
                        StringBuilder fullMeaningBuilder = new StringBuilder();
                        foreach (KanjiMeaning meaning in meanings)
                        {
                            fullMeaningBuilder.Append(meaning.Meaning);
                            if (meaning != meanings.Last())
                            {
                                fullMeaningBuilder.Append(", ");
                            }
                        }

                        // Return the formatted meanings string.
                        return(fullMeaningBuilder.ToString());
                    }
                }
            }
            else
            {
                // Invalid arguments.
                throw new ArgumentException(
                          "This converter needs a KanjiEntity as a value and a ConversionType as a parameter.");
            }

            // There are no meanings to display.
            return("(No meaning)");
        }
Exemplo n.º 15
0
 public ExtendedKanji(KanjiEntity dbKanji)
 {
     DbKanji = dbKanji;
     RadicalStore.Instance.IssueWhenLoaded(OnRadicalsLoaded);
 }
Exemplo n.º 16
0
        /// <summary>
        /// Builds and returns the vocab filter SQL clauses from the given
        /// filters.
        /// </summary>
        internal string BuildVocabFilterClauses(List <DaoParameter> parameters,
                                                KanjiEntity kanji,
                                                string readingFilter, string meaningFilter, VocabCategory categoryFilter,
                                                int jlptLevel, int wkLevel)
        {
            const int minJlptLevel = Levels.MinJlptLevel;
            const int maxJlptLevel = Levels.MaxJlptLevel;
            const int minWkLevel   = Levels.MinWkLevel;
            const int maxWkLevel   = Levels.MaxWkLevel;

            string sqlJlptFilter = string.Empty;

            if (jlptLevel >= minJlptLevel && jlptLevel <= maxJlptLevel)
            {
                sqlJlptFilter = string.Format("v.{0}=@jlpt ",
                                              SqlHelper.Field_Vocab_JlptLevel);

                parameters.Add(new DaoParameter("@jlpt", jlptLevel));
            }
            else if (jlptLevel < minJlptLevel)
            {
                sqlJlptFilter = string.Format("v.{0} IS NULL ",
                                              SqlHelper.Field_Vocab_JlptLevel);
            }

            string sqlWkFilter = string.Empty;

            if (wkLevel >= minWkLevel && wkLevel <= maxWkLevel)
            {
                sqlWkFilter = string.Format("v.{0}=@wk ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);

                parameters.Add(new DaoParameter("@wk", wkLevel));
            }
            else if (wkLevel > maxWkLevel)
            {
                sqlWkFilter = string.Format("v.{0} IS NULL ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);
            }

            string sqlKanjiFilter = string.Empty;

            if (kanji != null)
            {
                // Build the sql kanji filter clause.
                // Example with the kanji '達' :
                //
                // WHERE v.KanjiWriting LIKE '%達%'

                sqlKanjiFilter = string.Format("v.{0} LIKE @kanji ",
                                               SqlHelper.Field_Vocab_KanjiWriting);

                parameters.Add(new DaoParameter("@kanji", "%" + kanji.Character + "%"));
            }

            string sqlReadingFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(readingFilter))
            {
                // Build the sql reading filter clause.
                // Example with readingFilter="かな" :
                //
                // WHERE v.KanaWriting LIKE '%かな%' OR
                // v.KanjiWriting LIKE '%かな%'

                sqlReadingFilter = string.Format("(v.{0} LIKE @reading OR v.{1} LIKE @reading) ",
                                                 SqlHelper.Field_Vocab_KanaWriting,
                                                 SqlHelper.Field_Vocab_KanjiWriting);

                parameters.Add(new DaoParameter("@reading", "%" + readingFilter + "%"));
            }

            string sqlSharedJoins = string.Empty;

            string sqlMeaningFilterJoins = string.Empty;
            string sqlMeaningFilter      = string.Empty;

            if (!string.IsNullOrWhiteSpace(meaningFilter))
            {
                // Build the sql meaning filter clause and join clauses.
                // Example of filter clause with meaningFilter="test" :
                //
                // WHERE vm.Meaning LIKE '%test%'

                // First, build the join clause if it does not already exist. This will be included before the filters.
                if (string.IsNullOrEmpty(sqlSharedJoins))
                {
                    sqlSharedJoins = joinString_VocabEntity_VocabMeaning;
                }
                sqlMeaningFilterJoins = joinString_VocabMeaningSet;

                // Once the join clauses are done, build the filter itself.
                sqlMeaningFilter = string.Format("vm.{0} LIKE @meaning ",
                                                 SqlHelper.Field_VocabMeaning_Meaning);

                parameters.Add(new DaoParameter("@meaning", "%" + meaningFilter + "%"));
            }

            string sqlCategoryFilterJoins = string.Empty;
            string sqlCategoryFilter      = string.Empty;

            if (categoryFilter != null)
            {
                // Build the filter clause for the vocab category.
                // Note that the category is actually associated either with the vocab itself or with a MEANING,
                // so we need to grab any vocab which itself has said category, or of which ONE OF THE MEANINGS
                // is of said category.
                // Example of filter clause with category.ID=42 :
                //
                // WHERE vc.Categories_ID=42 OR mc.Categories_ID=42

                if (string.IsNullOrEmpty(sqlSharedJoins))
                {
                    sqlSharedJoins = joinString_VocabEntity_VocabMeaning;
                }

                /* TODO: Currently, only the meanings are checked for category matches, not vocab items themselves.
                 * This is because of several reasons:
                 *
                 * 1) In the current database, not a single vocab has a category attached.
                 *    Only meanings do.
                 * 2) Saving some performance by not doing a check that does not do anything.
                 *
                 * This does mean that this query must be changed if vocab items ever
                 * get a category attached to them.
                 *
                 * Actually, scratch that. Ateji DO have a category attached to the vocab themselves.
                 */

                string subQuery = string.Format("(SELECT m.{0} FROM {1} m WHERE m.{2}=@cat)",
                                                SqlHelper.Field_VocabMeaning_VocabCategory_VocabMeaningId,
                                                SqlHelper.Table_VocabMeaning_VocabCategory,
                                                SqlHelper.Field_VocabMeaning_VocabCategory_VocabCategoryId);

                // First, build the join clause if it does not already exist. This will be included before the filters.
                sqlCategoryFilterJoins = string.IsNullOrEmpty(sqlMeaningFilterJoins) ? joinString_VocabMeaningSet : null;

                // Once the join clauses are done, build the filter itself.
                sqlCategoryFilter = string.Format("vm.{0} IN {1} ",
                                                  SqlHelper.Field_VocabMeaning_Id, subQuery);

                parameters.Add(new DaoParameter("@cat", categoryFilter.ID));
            }

            string[] sqlArgs =
            {
                sqlSharedJoins,
                sqlMeaningFilterJoins,
                sqlCategoryFilterJoins,
                sqlJlptFilter,
                sqlWkFilter,
                sqlKanjiFilter,
                sqlReadingFilter,
                sqlMeaningFilter,
                sqlCategoryFilter
            };

            bool isFiltered = false;

            for (int i = 0; i < sqlArgs.Length; i++)
            {
                string arg = sqlArgs[i];
                if (string.IsNullOrEmpty(arg) || arg.StartsWith("JOIN"))
                {
                    continue;
                }

                sqlArgs[i] = (isFiltered ? "AND " : "WHERE ") + arg;
                isFiltered = true;
            }

            return(string.Concat(sqlArgs));
        }
Exemplo n.º 17
0
 public void LoadFromKanji(KanjiEntity k)
 {
     Reference.LoadFromKanji(k);
     RaisePropertyChanged("Meanings");
     RaisePropertyChanged("Readings");
 }
Exemplo n.º 18
0
        /// <summary>
        /// Reads the KanjiDic2 file and outputs kanji entities parsed from the file.
        /// </summary>
        /// <returns>Kanji entities parsed from the file.</returns>
        private IEnumerable <KanjiEntity> ReadKanjiDic2()
        {
            // Load the KanjiDic2 file.
            XDocument xdoc = XDocument.Load(PathHelper.KanjiDic2Path);

            // Browse kanji nodes.
            foreach (XElement xkanji in xdoc.Root.Elements(XmlNode_Character))
            {
                // For each kanji node, read values.
                KanjiEntity kanji = new KanjiEntity();

                // Read the kanji character.
                kanji.Character = xkanji.Element(XmlNode_Literal).Value;

                // In the code point node...
                XElement xcodePoint = xkanji.Element(XmlNode_CodePoint);
                if (xcodePoint != null)
                {
                    // Try to read the unicode character value.
                    XElement xunicode = xcodePoint.Elements(XmlNode_CodePointValue)
                                        .Where(x => x.ReadAttributeString(XmlAttribute_CodePointType) == XmlAttributeValue_CodePointUnicode)
                                        .FirstOrDefault();

                    if (xunicode != null)
                    {
                        string unicodeValueString = xunicode.Value;
                        int    intValue           = 0;
                        if (int.TryParse(unicodeValueString, System.Globalization.NumberStyles.HexNumber, ParsingHelper.DefaultCulture, out intValue))
                        {
                            kanji.UnicodeValue = intValue;
                        }
                    }
                }

                // In the misc node...
                XElement xmisc = xkanji.Element(XmlNode_Misc);
                if (xmisc != null)
                {
                    // Try to read the grade, stroke count, frequency and JLPT level.
                    // Update: JLPT level is outdated in this file. Now using the JLPTKanjiList.
                    XElement xgrade       = xmisc.Element(XmlNode_Grade);
                    XElement xstrokeCount = xmisc.Element(XmlNode_StrokeCount);
                    XElement xfrequency   = xmisc.Element(XmlNode_Frequency);
                    //XElement xjlpt = xmisc.Element(XmlNode_JlptLevel);

                    if (xgrade != null)
                    {
                        kanji.Grade = ParsingHelper.ParseShort(xgrade.Value);
                    }
                    if (xstrokeCount != null)
                    {
                        kanji.StrokeCount = ParsingHelper.ParseShort(xstrokeCount.Value);
                    }
                    if (xfrequency != null)
                    {
                        kanji.NewspaperRank = ParsingHelper.ParseInt(xfrequency.Value);
                    }
                    //if (xjlpt != null) kanji.JlptLevel = ParsingHelper.ParseShort(xjlpt.Value);
                }

                // Find the JLPT level using the dictionary.
                if (_jlptDictionary.ContainsKey(kanji.Character))
                {
                    kanji.JlptLevel = _jlptDictionary[kanji.Character];
                }

                // Find the frequency rank using the dictionary.
                if (_frequencyRankDictionary.ContainsKey(kanji.Character))
                {
                    kanji.MostUsedRank = _frequencyRankDictionary[kanji.Character];
                }

                // Find the WaniKani level using the dictionary.
                if (_waniKaniDictionary.ContainsKey(kanji.Character))
                {
                    kanji.WaniKaniLevel = _waniKaniDictionary[kanji.Character];
                }

                // In the reading/meaning node...
                XElement xreadingMeaning = xkanji.Element(XmlNode_ReadingMeaning);
                if (xreadingMeaning != null)
                {
                    // Read the nanori readings.
                    kanji.Nanori = string.Empty;
                    foreach (XElement xnanori in xreadingMeaning.Elements(XmlNode_Nanori))
                    {
                        kanji.Nanori += xnanori.Value + MultiValueFieldHelper.ValueSeparator;
                    }
                    kanji.Nanori = kanji.Nanori.Trim(MultiValueFieldHelper.ValueSeparator);

                    // Browse the reading group...
                    XElement xrmGroup = xreadingMeaning.Element(XmlNode_ReadingMeaningGroup);
                    if (xrmGroup != null)
                    {
                        // Read the on'yomi readings.
                        kanji.OnYomi = string.Empty;
                        foreach (XElement xonYomi in xrmGroup.Elements(XmlNode_Reading)
                                 .Where(x => x.Attribute(XmlAttribute_ReadingType).Value == XmlAttributeValue_OnYomiReading))
                        {
                            kanji.OnYomi += xonYomi.Value + MultiValueFieldHelper.ValueSeparator;
                        }
                        kanji.OnYomi = KanaHelper.ToHiragana(kanji.OnYomi.Trim(MultiValueFieldHelper.ValueSeparator));

                        // Read the kun'yomi readings.
                        kanji.KunYomi = string.Empty;
                        foreach (XElement xkunYomi in xrmGroup.Elements(XmlNode_Reading)
                                 .Where(x => x.Attribute(XmlAttribute_ReadingType).Value == XmlAttributeValue_KunYomiReading))
                        {
                            kanji.KunYomi += xkunYomi.Value + MultiValueFieldHelper.ValueSeparator;
                        }
                        kanji.KunYomi = kanji.KunYomi.Trim(MultiValueFieldHelper.ValueSeparator);

                        // Browse the meanings...
                        foreach (XElement xmeaning in xrmGroup.Elements(XmlNode_Meaning))
                        {
                            // Get the language and meaning.
                            XAttribute xlanguage = xmeaning.Attribute(XmlAttribute_MeaningLanguage);
                            string     language  = xlanguage != null?xlanguage.Value.ToLower() : null;

                            string meaning = xmeaning.Value;

                            if (xlanguage == null || language.ToLower() == "en")
                            {
                                // Build a meaning.
                                KanjiMeaning kanjiMeaning = new KanjiMeaning()
                                {
                                    Kanji = kanji, Language = language, Meaning = meaning
                                };

                                // Add the meaning to the kanji.
                                kanji.Meanings.Add(kanjiMeaning);
                            }
                        }
                    }
                }

                // Return the kanji read and go to the next kanji node.
                yield return(kanji);

                xkanji.RemoveAll();
            }
        }
Exemplo n.º 19
0
        /// <summary>
        /// Loads and returns vocab items from the JMDict XDocument.
        /// </summary>
        /// <param name="xdoc">Loaded JMDict XDocument.</param>
        /// <returns>Vocab loaded from the file.</returns>
        private IEnumerable <VocabEntity> LoadVocabItems(XDocument xdoc)
        {
            // Browse each vocab entry.
            foreach (XElement xentry in xdoc.Root.Elements(XmlNode_Entry))
            {
                List <VocabEntity> vocabList = new List <VocabEntity>();

                long seq = long.Parse(xentry.Element(XmlNode_EntSeq).Value);
                // For each kanji element node
                foreach (XElement xkanjiElement in xentry.Elements(XmlNode_KanjiElement))
                {
                    // Parse the kanji element. The list will be expanded with new elements.
                    ParseKanji(xkanjiElement, vocabList, seq);
                }

                // For each kanji reading node
                var xreadingElements = xentry.Elements(XmlNode_ReadingElement);
                foreach (XElement xreadingElement in xreadingElements)
                {
                    // Exclude the node if it contains the no kanji node, and is not the only reading.
                    // This is a behavior that seems to be implemented in Jisho (example word: 台詞).
                    if (xreadingElement.HasElement(XmlNode_NoKanji) && xreadingElements.Count() > 1)
                    {
                        continue;
                    }

                    // Parse the reading. The list will be expanded and/or its elements filled with
                    // the available info.
                    ParseReading(xreadingElement, vocabList, seq);
                }

                // For each kanji meaning node
                foreach (XElement xmeaningElement in xentry.Elements(XmlNode_Meaning))
                {
                    // Parse the meaning node. The list will be updated with the available info.
                    ParseMeaning(xmeaningElement, vocabList);
                }

                // Now we will define the vocab <-> kanji relationships.
                // For each vocab
                bool first = true;
                foreach (VocabEntity vocab in vocabList)
                {
                    // If the kanji vocab is defined
                    if (!string.IsNullOrEmpty(vocab.KanjiWriting))
                    {
                        // Browse each character
                        foreach (char c in vocab.KanjiWriting)
                        {
                            // Attempt to find a kanji matching the character.
                            string      s     = c.ToString();
                            KanjiEntity kanji = _kanjiDictionary.ContainsKey(s) ? _kanjiDictionary[s] : null;
                            if (kanji != null)
                            {
                                // If a kanji is found, create a relationship between the entities.
                                vocab.Kanji.Add(kanji);
                            }
                        }
                    }

                    if (first)
                    {
                        // Set the first vocab as the main variant.
                        first        = false;
                        vocab.IsMain = true;
                    }
                    else
                    {
                        // For now, we are saying that non-main vocab cannot be common.
                        // Otherwise, too much variants are marked as common and it can
                        // be confusing.
                        vocab.IsCommon = false;
                    }

                    // Return the vocab and continue to the next one.
                    yield return(vocab);
                }
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// Builds and returns the vocab filter SQL clauses from the given
        /// filters.
        /// </summary>
        internal string BuildVocabFilterClauses(List <DaoParameter> parameters,
                                                KanjiEntity kanji,
                                                string readingFilter, string meaningFilter, VocabCategory categoryFilter,
                                                int jlptLevel, int wkLevel)
        {
            const int minJlptLevel = Levels.MinJlptLevel;
            const int maxJlptLevel = Levels.MaxJlptLevel;
            const int minWkLevel   = Levels.MinWkLevel;
            const int maxWkLevel   = Levels.MaxWkLevel;

            string sqlJlptFilter = string.Empty;

            if (jlptLevel >= minJlptLevel && jlptLevel <= maxJlptLevel)
            {
                sqlJlptFilter = string.Format("v.{0}=@jlpt ",
                                              SqlHelper.Field_Vocab_JlptLevel);

                parameters.Add(new DaoParameter("@jlpt", jlptLevel));
            }
            else if (jlptLevel < minJlptLevel)
            {
                sqlJlptFilter = string.Format("v.{0} IS NULL ",
                                              SqlHelper.Field_Vocab_JlptLevel);
            }

            string sqlWkFilter = string.Empty;

            if (wkLevel >= minWkLevel && wkLevel <= maxWkLevel)
            {
                sqlWkFilter = string.Format("v.{0}=@wk ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);

                parameters.Add(new DaoParameter("@wk", wkLevel));
            }
            else if (wkLevel > maxWkLevel)
            {
                sqlWkFilter = string.Format("v.{0} IS NULL ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);
            }

            string sqlKanjiFilter = string.Empty;

            if (kanji != null)
            {
                // Build the sql kanji filter clause.
                // Example with the kanji '達' :
                //
                // WHERE v.KanjiWriting LIKE '%達%'

                sqlKanjiFilter = string.Format("v.{0} LIKE @kanji ",
                                               SqlHelper.Field_Vocab_KanjiWriting);

                parameters.Add(new DaoParameter("@kanji", "%" + kanji.Character + "%"));
            }

            string sqlReadingFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(readingFilter))
            {
                // Build the sql reading filter clause.
                // Example with readingFilter="かな" :
                //
                // WHERE v.KanaWriting LIKE '%かな%' OR
                // v.KanjiWriting LIKE '%かな%'

                sqlReadingFilter = string.Format("(v.{0} LIKE @reading OR v.{1} LIKE @reading) ",
                                                 SqlHelper.Field_Vocab_KanaWriting,
                                                 SqlHelper.Field_Vocab_KanjiWriting);

                parameters.Add(new DaoParameter("@reading", "%" + readingFilter + "%"));
            }

            string sqlSharedJoins = string.Empty;

            string sqlMeaningFilterJoins = string.Empty;
            string sqlMeaningFilter      = string.Empty;

            if (!string.IsNullOrWhiteSpace(meaningFilter))
            {
                // Build the sql meaning filter clause and join clauses.
                // Example of filter clause with meaningFilter="test" :
                //
                // WHERE vm.Meaning LIKE '%test%'

                // First, build the join clause. This will be included before the filters.
                if (string.IsNullOrEmpty(sqlSharedJoins))
                {
                    sqlSharedJoins = string.Format("JOIN {0} vvm ON (vvm.{1}=v.{2}) ",
                                                   SqlHelper.Table_Vocab_VocabMeaning,
                                                   SqlHelper.Field_Vocab_VocabMeaning_VocabId,
                                                   SqlHelper.Field_Vocab_Id);
                }
                sqlMeaningFilterJoins = string.Format("JOIN {0} vm ON (vm.{1}=vvm.{2}) ",
                                                      SqlHelper.Table_VocabMeaning,
                                                      SqlHelper.Field_VocabMeaning_Id,
                                                      SqlHelper.Field_Vocab_VocabMeaning_VocabMeaningId);
                // Ouch... it looks kinda like an obfuscated string... Sorry.
                // Basically, you just join the vocab to its meaning entries.

                // Once the join clauses are done, build the filter itself.
                sqlMeaningFilter = string.Format("vm.{0} LIKE @meaning ",
                                                 SqlHelper.Field_VocabMeaning_Meaning);

                parameters.Add(new DaoParameter("@meaning", "%" + meaningFilter + "%"));
            }

            string sqlCategoryFilterJoins = string.Empty;
            string sqlCategoryFilter      = string.Empty;

            if (categoryFilter != null)
            {
                // Build the filter clause for the vocab category.
                // Note that the category is actually associated either with the vocab itself or with a MEANING,
                // so we need to grab any vocab which itself has said category, or of which ONE OF THE MEANINGS
                // is of said category.
                // Example of filter clause with category.ID=42 :
                //
                // WHERE vc.Categories_ID=42 OR mc.Categories_ID=42

                if (string.IsNullOrEmpty(sqlSharedJoins))
                {
                    sqlSharedJoins = string.Format("JOIN {0} vvm ON (vvm.{1}=v.{2}) ",
                                                   SqlHelper.Table_Vocab_VocabMeaning,
                                                   SqlHelper.Field_Vocab_VocabMeaning_VocabId,
                                                   SqlHelper.Field_Vocab_Id);
                }

                sqlCategoryFilterJoins = string.Format(
                    "JOIN {0} vc ON (vc.{1}=v.{2}) JOIN {3} mc ON (mc.{4}=vvm.{5}) ",
                    SqlHelper.Table_VocabCategory_Vocab,
                    SqlHelper.Field_VocabCategory_Vocab_VocabId,
                    SqlHelper.Field_VocabCategory_Id,
                    SqlHelper.Table_VocabMeaning_VocabCategory,
                    SqlHelper.Field_VocabMeaning_VocabCategory_VocabMeaningId,
                    SqlHelper.Field_Vocab_VocabMeaning_VocabMeaningId);

                sqlCategoryFilter = string.Format("(vc.{0}=@cat OR mc.{1}=@cat) ",
                                                  SqlHelper.Field_VocabCategory_Vocab_VocabCategoryId,
                                                  SqlHelper.Field_VocabMeaning_VocabCategory_VocabCategoryId);

                parameters.Add(new DaoParameter("@cat", categoryFilter.ID));
            }

            string[] sqlArgs =
            {
                sqlSharedJoins,
                sqlMeaningFilterJoins,
                sqlCategoryFilterJoins,
                sqlJlptFilter,
                sqlWkFilter,
                sqlKanjiFilter,
                sqlReadingFilter,
                sqlMeaningFilter,
                sqlCategoryFilter
            };

            bool isFiltered = false;

            for (int i = 0; i < sqlArgs.Length; i++)
            {
                string arg = sqlArgs[i];
                if (string.IsNullOrEmpty(arg) || arg.StartsWith("JOIN"))
                {
                    continue;
                }

                sqlArgs[i] = (isFiltered ? "AND " : "WHERE ") + arg;
                isFiltered = true;
            }

            return(string.Concat(sqlArgs));
        }