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 } }); }
public static string ToWordName(DocRef docRef) { return(string.Format("words/{0}", DocRefs.Encode(docRef))); }
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); }