Ejemplo n.º 1
0
        public async override Task <Yngdieng.Frontend.V3.Protos.Word> GetWord(GetWordRequest request,
                                                                              ServerCallContext context)
        {
            if (string.IsNullOrEmpty(request.Name))
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, "name must not be empty"));
            }
            var docId = ResourceNames.ToDocId(request.Name);

            if (_indexHolder.GetIndex().DocIdRedirections.ContainsKey(docId))
            {
                var redirectionTarget = _indexHolder.GetIndex().DocIdRedirections[docId];
                _logger.LogInformation($"DocId Redirection: {docId} -> {redirectionTarget}");
                docId = redirectionTarget;
            }
            DocRef docRef;

            try
            {
                docRef = DocRefs.Decode(docId);
            }
            catch (Exception e)
            {
                throw new RpcException(new Status(StatusCode.InvalidArgument, $"{request.Name} is not a valid name.", e));
            }
            var userPreference = UserPreferences.FromContext(context);
            var zhConverter    = new ZhConverter(_openCc, userPreference.ZhConversionPreference);

            return(await Words.GetWord(_indexHolder, _dbContext, zhConverter, docRef));
        }
Ejemplo n.º 2
0
        public static async Task <Word> GetWord(
            IIndexHolder _indexHolder,
            AdminContext _dbContext,
            ZhConverter zhConverter,
            DocRef docRef,
            Mode mode = Mode.Full)
        {
            var maybeYngdiengDocument = _indexHolder.GetIndex().YngdiengDocuments
                                        .SingleOrDefault(yDoc => yDoc.DocId == DocRefs.Encode(docRef));
            var maybeWordId = string.IsNullOrEmpty(docRef.ZingzeuId)
                ? (int?)null : int.Parse(docRef.ZingzeuId, NumberStyles.HexNumber);
            var maybeWord = maybeWordId == null
                ? null
                : await _dbContext.Words
                            .Where(w => w.WordId == maybeWordId)
                            .Include(w => w.PreferredSandhiAudio)
                            .SingleOrDefaultAsync();

            if (maybeYngdiengDocument == null && maybeWord == null)
            {
                throw new RpcException(new Status(StatusCode.NotFound, "Not found."));
            }
            var extensions = await _dbContext.Extensions.Where(e => e.WordId == maybeWordId).ToListAsync();

            var prons = await _dbContext.Prons.Where(p => p.WordId == maybeWordId).ToListAsync();

            var hanzi            = zhConverter.tH(await GetHanzi(_dbContext, maybeYngdiengDocument, maybeWordId));
            var recommendedProns = mode == Mode.Snippet
                ? PronChooser.GetSnippetPronunciations(maybeYngdiengDocument, prons, maybeWord?.PreferredSandhiAudio)
                : PronChooser.GetRecommendedPronunciations(maybeYngdiengDocument, prons, maybeWord?.PreferredSandhiAudio);
            var explanations = mode == Mode.Snippet
                ? Enumerable.Empty <RichTextNode>()
                : GetExplanations(zhConverter, hanzi, maybeYngdiengDocument, extensions);
            var audioCards = mode == Mode.Snippet ? Enumerable.Empty <Word.Types.AudioCard>()
                : await GetAudioCards(_dbContext, recommendedProns, maybeWordId);

            var wordLists = mode == Mode.Full && maybeWordId.HasValue
                ? await Queries.QueryWordListsByWordId(_dbContext, maybeWordId.Value).Select(wl => Renderers.ToWordList(wl)).ToListAsync()
                : Enumerable.Empty <WordList>();

            return(new Word
            {
                Name = ResourceNames.ToWordName(docRef),
                Hanzi = hanzi,
                Pronunciations = { recommendedProns },
                Explanation = { explanations },
                Snippet = zhConverter.tH(GetSnippet(maybeYngdiengDocument, extensions)),
                AudioCards = { audioCards },
                WordLists =
                {
                    wordLists
                }
            });
        }
Ejemplo n.º 3
0
 public static string ToWordName(DocRef docRef)
 {
     return(string.Format("words/{0}", DocRefs.Encode(docRef)));
 }
Ejemplo n.º 4
0
        public static IEnumerable <YngdiengDocument> Combine(
            IEnumerable <zingzeudata.ZingzeuData.Models.ZingzeuEntry> zingzeuEntries,
            IEnumerable <HistoricalDocument> historicalDocs,
            IEnumerable <FengDocument> fengDocs,
            IEnumerable <ContribDocument> contribDocs)
        {
            var results           = new List <YngdiengDocument>();
            var pendingFeng       = new List <FengDocument>(fengDocs);
            var pendingHistorical = new List <HistoricalDocument>(historicalDocs);
            var pendingContrib    = new List <ContribDocument>(contribDocs);

            // 第一阶段: 有 zingzeu_id 的,按相同 zingzeu_id 合并成 YngdiengDocument
            foreach (var zingzeuWordsEntry in zingzeuEntries)
            {
                var zingzeuId = zingzeuWordsEntry.Id;
                var tmp       = new YngdiengDocument
                {
                    DocRef = new Yngdieng.Protos.DocRef {
                        ZingzeuId = zingzeuId
                    },
                    HanziCanonical = new Hanzi {
                        Regular = zingzeuWordsEntry.Hanzi
                    },
                    YngpingSandhi     = FindZingzeuWordsPron(zingzeuWordsEntry) ?? string.Empty,
                    YngpingUnderlying =
                        FindZingzeuWordsPron(zingzeuWordsEntry,
                                             ZingzeuEntry.Types.ZingzeuPron.Types.SandhiCategory.Bengzi) ?? string.Empty,
                    HanziAlternatives = { zingzeuWordsEntry.HanziAlt.Select(a => new Hanzi {
                            Regular = a
                        }) },
                    IndexingExtension = new YngdiengDocument.Types.IndexingExtension
                    {
                        MandarinWords = { zingzeuWordsEntry.MandarinWords }
                    }
                };

                var historicalMatches = pendingHistorical.Where(h => h.ZingzeuId == zingzeuId).ToArray();
                foreach (var historicalMatch in historicalMatches)
                {
                    pendingHistorical.Remove(historicalMatch);
                    tmp.Sources.Add(new YngdiengDocument.Types.Source {
                        CiklinDfd = historicalMatch
                    });
                }

                var fengMatches = pendingFeng.Where(f => f.ZingzeuId == zingzeuId).ToArray();
                foreach (var fengMatch in fengMatches)
                {
                    pendingFeng.Remove(fengMatch);
                    tmp.Sources.Add(new YngdiengDocument.Types.Source {
                        Feng = fengMatch
                    });
                }

                var contribMatches =
                    pendingContrib.Where(c => c.ZingzeuId == zingzeuId).ToList();
                foreach (var contribMatch in contribMatches)
                {
                    pendingContrib.Remove(contribMatch);
                    tmp.Sources.Add(new YngdiengDocument.Types.Source {
                        Contrib = contribMatch
                    });
                }

                results.Add(tmp);
            }
            Console.WriteLine($"{results.Count} matched.");
            // 第二阶段: 无 zingzeu_id 的,各自单独生成 YngdiengDocument
            Console.WriteLine($"{pendingHistorical.Count} unmatched historicalDocs.");
            Console.WriteLine($"{pendingFeng.Count} unmatched fengDocs.");
            Console.WriteLine($"{pendingContrib.Count} unmatched contribDocs.");
            foreach (var h in pendingHistorical)
            {
                results.Add(new YngdiengDocument
                {
                    DocRef = new Yngdieng.Protos.DocRef {
                        HistoricalDocId = h.Id
                    },
                    Sources = { new YngdiengDocument.Types.Source {
                                    CiklinDfd = h
                                } }
                });
            }
            foreach (var f in pendingFeng)
            {
                results.Add(
                    new YngdiengDocument
                {
                    DocRef = new Yngdieng.Protos.DocRef {
                        FengId = f.Id
                    },
                    Sources = { new YngdiengDocument.Types.Source {
                                    Feng = f
                                } }
                });
            }
            foreach (var c in pendingContrib)
            {
                results.Add(new YngdiengDocument
                {
                    DocRef = new Yngdieng.Protos.DocRef {
                        ContribRowNumber = c.RowNumber
                    },
                    Sources = { new YngdiengDocument.Types.Source {
                                    Contrib = c
                                } }
                });
            }
            foreach (var doc in results)
            {
                doc.DocId             = DocRefs.Encode(doc.DocRef);
                doc.HanziCanonical    = FindHanziCanonical(doc.Sources, doc.HanziCanonical);
                doc.YngpingUnderlying = FindYngpingUnderlying(doc.Sources, doc.YngpingUnderlying);
                doc.YngpingSandhi     = FindYngpingSandhi(doc.Sources, doc.YngpingSandhi);
                doc.IndexingExtension ??= new YngdiengDocument.Types.IndexingExtension {
                };
                doc.IndexingExtension.YngpingPermutations.AddRange(CollectYngpingPermutations(doc.Sources));
                doc.IndexingExtension.HanziMatchable.AddRange(CollectHanziMatchable(doc.Sources));
                doc.IndexingExtension.ExplanationText.AddRange(CollectExplanationTexts(doc.Sources));
            }
            return(results);
        }