示例#1
0
        public IActionResult SaveFullEntry([FromForm] string entryId, [FromForm] string hw, [FromForm] string trg,
                                           [FromForm] string note, [FromForm] string lang)
        {
            if (entryId == null || hw == null || trg == null || note == null || lang == null)
            {
                return(StatusCode(400, "Missing parameter(s)."));
            }

            // Must be authenticated user
            int    userId;
            string userName;

            auth.CheckSession(HttpContext.Request.Headers, out userId, out userName);
            if (userId < 0)
            {
                return(StatusCode(401, "Request must contain authentication token."));
            }

            EditEntryResult res = new EditEntryResult();

            int idVal = EntryId.StringToId(entryId);

            trg = trg.Replace("\r\n", "\n");
            trg = trg.Replace('/', '\\');
            trg = trg.Replace('\n', '/');
            trg = "/" + trg + "/";
            CedictParser parser = new CedictParser();
            CedictEntry  entry  = null;

            try { entry = parser.ParseEntry(hw + " " + trg, 0, null); }
            catch { }
            if (entry == null)
            {
                res.Error = TextProvider.Instance.GetString(lang, "editEntry.badDataOnSave");
                return(new ObjectResult(res));
            }

            bool persisted;

            using (SqlDict.SimpleBuilder builder = dict.GetSimpleBuilder(userId))
            {
                persisted = builder.ChangeHeadAndTarget(userId, idVal, hw, trg, note);
            }
            // Not persisted: violates uniqueness constraint
            if (!persisted)
            {
                res.Error = TextProvider.Instance.GetString(lang, "editEntry.duplicateOnSave");
                return(new ObjectResult(res));
            }

            // Refresh cached contrib score
            auth.RefreshUserInfo(userId);
            // Tell our caller we dun it
            res.Success = true;
            return(new ObjectResult(res));
        }
示例#2
0
        private void dictLine(string line, bool cedict, BinWriter bw)
        {
            if (line == "" || line.StartsWith("#"))
            {
                return;
            }
            // Parse entry
            CedictEntry entry = parser.ParseEntry(line, 0, null);

            // Verify that simp, trad and pinyin are equal length
            if (entry != null)
            {
                if (entry.ChSimpl.Length != entry.ChTrad.Length || entry.ChSimpl.Length != entry.PinyinCount)
                {
                    entry = null;
                }
            }
            // Just count if failed to parse
            if (entry == null)
            {
                if (cedict)
                {
                    ++cedictDropped;
                }
                else
                {
                    ++hddDropped;
                }
                return;
            }
            // Serialize
            int fpos = bw.Position;

            // First: hash chain: next entry in file with same hash. Will fill later.
            bw.WriteInt(0);
            // Then, entry itself
            entry.Serialize(bw);
            // Hash simplified and remember file position
            int        hash = CedictEntry.Hash(entry.ChSimpl);
            List <int> poss;
            Dictionary <int, List <int> > hashPoss = cedict ? cedictHashPoss : hddHashPoss;

            if (!hashPoss.ContainsKey(hash))
            {
                poss           = new List <int>();
                hashPoss[hash] = poss;
            }
            else
            {
                poss = hashPoss[hash];
            }
            poss.Add(fpos);
        }
示例#3
0
        /// <summary>
        /// Import new entries from file as a single bulk change.
        /// </summary>
        public void BulkAdd(string dictPath, string workingFolder)
        {
            CedictParser parser = new CedictParser();

            Startup.InitDB(config, null, false);
            SqlDict dict    = new SqlDict(null, mut);
            int     lineNum = 0;

            DateTime dt    = DateTime.Now;
            string   fnLog = "importlog-" + dt.Year + "-" + dt.Month.ToString("00") + "-" + dt.Day.ToString("00") + "!" + dt.Hour.ToString("00") + "-" + dt.Minute.ToString("00") + "-" + dt.Second.ToString("00") + ".txt";

            fnLog = Path.Combine(workingFolder, fnLog);
            using (FileStream fs = new FileStream(dictPath, FileMode.Open, FileAccess.Read))
                using (StreamReader sr = new StreamReader(fs))
                    using (FileStream fsLog = new FileStream(fnLog, FileMode.Create, FileAccess.ReadWrite))
                        using (StreamWriter swLog = new StreamWriter(fsLog))
                        {
                            // First two lines are commented and have metainfo
                            // First line: user name
                            // Second line: bulk change's comment
                            string user = sr.ReadLine().Substring(1).Trim();
                            string note = sr.ReadLine().Substring(1).Trim();
                            lineNum = 2;
                            using (SqlDict.ImportBuilder builder = dict.GetBulkBuilder(user, note))
                            {
                                string line;
                                while ((line = sr.ReadLine()) != null)
                                {
                                    ++lineNum;
                                    if (line == "" || line.StartsWith("#"))
                                    {
                                        continue;
                                    }
                                    CedictEntry entry = parser.ParseEntry(line, lineNum, swLog);
                                    if (entry == null)
                                    {
                                        swLog.WriteLine(line);
                                        continue;
                                    }
                                    entry.Status = EntryStatus.Approved;
                                    bool ok = builder.AddNewEntry(entry);
                                    if (!ok)
                                    {
                                        swLog.WriteLine("Line " + lineNum + ": Entry rejected by importer.");
                                        swLog.WriteLine(line);
                                        continue;
                                    }
                                }
                                builder.CommitRest();
                            }
                        }
        }
示例#4
0
        public void Work()
        {
            Random        rnd    = new Random(0);
            CedictParser  parser = new CedictParser();
            HashSet <int> idSet  = new HashSet <int>();
            StringBuilder sb     = new StringBuilder();

            using (FileStream fsIn = new FileStream("handedict.u8", FileMode.Open, FileAccess.Read))
                using (StreamReader sr = new StreamReader(fsIn))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (line.StartsWith("#"))
                        {
                            continue;
                        }
                        CedictEntry entry = parser.ParseEntry(line, 0, null);
                        if (entry == null)
                        {
                            continue;
                        }
                        if (entry.ChSimpl.Length > 16)
                        {
                            continue;
                        }

                        int id = rnd.Next();
                        while (idSet.Contains(id))
                        {
                            id = rnd.Next();
                        }
                        idSet.Add(id);
                        string strId   = EntryId.IdToString(id);
                        bool   isVerif = isVerified(entry);

                        sb.Clear();
                        // Line with ID
                        sb.AppendLine("# ID-" + strId);
                        // First version metainfo
                        string statStr = isVerif ? "Stat-Verif" : "Stat-New";
                        sb.AppendLine("# Ver 2011-05-28T01:27:49Z HanDeDict " + statStr + " 001>Originalversion HanDeDict-Datei");
                        // The entry itself
                        sb.AppendLine(CedictWriter.Write(entry));

                        items.Add(new ResItem {
                            ID = id, Lines = sb.ToString()
                        });
                    }
                }
        }
示例#5
0
        public void Work()
        {
            string line;

            while ((line = srDict.ReadLine()) != null)
            {
                ++lineNum;
                if (line.StartsWith("#"))
                {
                    continue;
                }
                CedictEntry entry = parser.ParseEntry(line, lineNum, swDiag);
                if (entry != null)
                {
                    string trippedLine = CedictWriter.Write(entry);
                    if (trippedLine != line)
                    {
                        swTrip.WriteLine(line);
                        swTrip.WriteLine(trippedLine);
                    }
                    countTags(line);
                }
            }
            List <TC> tlst = new List <TC>();

            foreach (var x in tags)
            {
                tlst.Add(new TC {
                    Tag = x.Key, Count = x.Value
                });
            }
            tlst.Sort((x, y) => y.Count.CompareTo(x.Count));
            using (FileStream fsTags = new FileStream("hdd-tags.txt", FileMode.Create, FileAccess.ReadWrite))
                using (StreamWriter sw = new StreamWriter(fsTags))
                {
                    foreach (var x in tlst)
                    {
                        sw.WriteLine(x.Count + "\t" + x.Tag);
                    }
                }
        }
示例#6
0
        public static CedictEntry BuildEntry(string simp, string trad, string pinyin, string trg)
        {
            // Prepare pinyin as list of proper syllables
            List <PinyinSyllable> pyList = new List <PinyinSyllable>();

            string[] pyRawArr = pinyin.Split(' ');
            foreach (string pyRaw in pyRawArr)
            {
                PinyinSyllable ps = PinyinSyllable.FromDisplayString(pyRaw);
                if (ps == null)
                {
                    ps = new PinyinSyllable(pyRaw, -1);
                }
                pyList.Add(ps);
            }

            // Build TRG entry in "canonical" form; parse; render
            trg = trg.Replace("\r\n", "\n");
            string[] senses = trg.Split('\n');
            string   can    = trad + " " + simp + " [";

            for (int i = 0; i != pyList.Count; ++i)
            {
                if (i != 0)
                {
                    can += " ";
                }
                can += pyList[i].GetDisplayString(false);
            }
            can += "] /";
            foreach (string str in senses)
            {
                can += str.Replace('/', '\\') + "/";
            }
            CedictParser parser = new CedictParser();

            return(parser.ParseEntry(can, 0, null));
        }
示例#7
0
        private static void histRenderChange(StringBuilder sb, ChangeItem ci, bool trailingSeparator, string lang,
                                             CedictParser parser, string extraItemClass = "")
        {
            var tprov = TextProvider.Instance;

            sb.AppendLine();
            string itemClass = "historyItem";

            if (!string.IsNullOrEmpty(extraItemClass))
            {
                itemClass += " " + extraItemClass;
            }
            if (ci.EntryId >= 0)
            {
                sb.AppendLine("<div class='" + itemClass + "' data-entry-id='" + EntryId.IdToString(ci.EntryId) + "'>");
            }
            else
            {
                sb.AppendLine("<div class='" + itemClass + "'>");
            }
            sb.AppendLine("<div class='changeHead'>");

            string iconClass = "";

            if (ci.ChangeType == ChangeType.New)
            {
                iconClass = "fa fa-lightbulb-o ctNew";
            }
            else if (ci.ChangeType == ChangeType.Edit)
            {
                iconClass = "fa fa-pencil-square-o ctEdit";
            }
            else if (ci.ChangeType == ChangeType.Note)
            {
                iconClass = "fa fa-commenting-o ctNote";
            }
            else if (ci.ChangeType == ChangeType.BulkImport)
            {
                iconClass = "fa fa-newspaper-o ctBulk";
            }
            else if (ci.ChangeType == ChangeType.StatusChange)
            {
                if (ci.EntryStatus == EntryStatus.Approved)
                {
                    iconClass = "fa fa-check-square-o ctApprove";
                }
                else if (ci.EntryStatus == EntryStatus.Flagged)
                {
                    iconClass = "fa fa-flag-o ctFlag";
                }
                else
                {
                    iconClass = "fa fa-flag-o ctUnflag";
                }
            }

            sb.Append("<i class='" + iconClass + "' />");
            sb.Append("<div class='changeSummary'>");

            string changeMsg = getChangeTypeStr(ci.ChangeType, ci.CountB, ci.EntryStatus, lang);
            string changeCls = "changeType";

            sb.Append("<span class='" + changeCls + "'>");
            sb.Append(HtmlEncoder.Default.Encode(changeMsg));
            sb.Append(" &bull; </span>");

            sb.Append("<span class='changeUser'>");
            sb.Append(HtmlEncoder.Default.Encode(ci.User));
            sb.Append("</span>");

            sb.Append("<span class='changeTime'>");
            sb.Append(HtmlEncoder.Default.Encode(getTimeStr(ci.When, lang)));
            sb.Append("</span>");

            if (ci.ChangeType != ChangeType.BulkImport && ci.CountA > 0)
            {
                sb.Append("<span class='revealPast'>+" + ci.CountA.ToString() + "</span>");
            }

            sb.Append("</div>"); // <div class='changeSummary'>

            sb.AppendLine("<div class='changeNote'>");
            if (ci.ChangeType == ChangeType.BulkImport)
            {
                string newCount = null;
                string chgCount = null;
                if (ci.CountA > 0)
                {
                    newCount = tprov.GetString(lang, "history.bulkNewWords");
                    newCount = string.Format(newCount, ci.CountA);
                }
                if (ci.CountB > 0)
                {
                    chgCount = tprov.GetString(lang, "history.bulkChangedWords");
                    chgCount = string.Format(chgCount, ci.CountB);
                }
                if (chgCount != null || newCount != null)
                {
                    sb.Append("<p>");
                    if (newCount != null)
                    {
                        sb.Append(HtmlEncoder.Default.Encode(newCount));
                    }
                    if (newCount != null && chgCount != null)
                    {
                        sb.Append(" &bull; ");
                    }
                    if (chgCount != null)
                    {
                        sb.Append(HtmlEncoder.Default.Encode(chgCount));
                    }
                    sb.Append("</p>");
                }
                sb.Append("<span class='bulkLink'>[");
                sb.Append("<a href='/" + lang + "/read/details/change-" + ci.BulkRef.ToString("000") + "' target='_blank'>");
                sb.Append(tprov.GetString(lang, "history.bulkLink") + "</a>");
                sb.Append("]</span> ");
            }
            sb.Append("<span class='changeNoteText'>");
            string note = HtmlEncoder.Default.Encode(ci.Note);

            note = note.Replace("&#xA;", "<br/>");
            sb.Append(note);
            sb.Append("</span>");
            sb.Append("</div>");

            sb.Append("</div>"); // <div class='changeHead'>

            sb.AppendLine("<div class='changeEntry'>");
            if (ci.ChangeType != ChangeType.BulkImport)
            {
                sb.AppendLine("<div class='histEntryOps'>");
                sb.Append("<a class='ajax' href='/" + lang + "/edit/existing/" + EntryId.IdToString(ci.EntryId) + "'>");
                sb.Append("<i class='opHistEdit fa fa-pencil'></i></a>");
                //sb.Append("<i class='opHistEdit fa fa-pencil' />");
                sb.Append("<i class='opHistComment fa fa-commenting-o' />");
                sb.Append("<i class='opHistFlag fa fa-flag-o' />");
                sb.Append("</div>"); // <div class='histEntryOps'>
            }

            if (ci.ChangeType != ChangeType.BulkImport)
            {
                // NOT edited
                if (ci.BodyBefore == null && ci.HeadBefore == null)
                {
                    CedictEntry entry = parser.ParseEntry(ci.EntryHead + " " + ci.EntryBody, 0, null);
                    entry.Status = ci.EntryStatus;
                    EntryRenderer er = new EntryRenderer(lang, entry, true);
                    er.OneLineHanziLimit = 12;
                    er.Render(sb, null);
                }
                // Entry edited: show "diff" in head and/or body
                else
                {
                    // Current, and comparison base
                    CedictEntry eCurr = parser.ParseEntry(ci.EntryHead + " " + ci.EntryBody, 0, null);
                    eCurr.Status = ci.EntryStatus;
                    string      headOld       = ci.HeadBefore == null ? ci.EntryHead : ci.HeadBefore;
                    string      bodyOld       = ci.BodyBefore == null ? ci.EntryBody : ci.BodyBefore;
                    CedictEntry eOld          = parser.ParseEntry(headOld + " " + bodyOld, 0, null);
                    bool        simpChanged   = eCurr.ChSimpl != eOld.ChSimpl;
                    bool        tradChanged   = eCurr.ChTrad != eOld.ChTrad;
                    bool        pinyinChanged = CedictWriter.WritePinyin(eCurr) != CedictWriter.WritePinyin(eOld);
                    bool        bodyChanged   = ci.BodyBefore != null;
                    // Render in parts
                    sb.AppendLine("<div class='entry'>");
                    // Let's not dim identical chars if anything changed in HW
                    EntryRenderer rCurr = new EntryRenderer(lang, eCurr, !simpChanged && !tradChanged);
                    EntryRenderer rOld  = new EntryRenderer(lang, eOld, !simpChanged && !tradChanged);
                    rCurr.OneLineHanziLimit = rOld.OneLineHanziLimit = 12;
                    rCurr.XRenderStatus(sb);
                    rCurr.XRenderHanzi(sb, simpChanged ? "new" : "", tradChanged ? "new" : "");
                    if (simpChanged || tradChanged)
                    {
                        rOld.XRenderHanzi(sb, simpChanged ? "old" : "", tradChanged ? "old" : "");
                    }
                    rCurr.XRenderPinyin(sb, pinyinChanged ? "new" : "");
                    if (pinyinChanged)
                    {
                        rOld.XRenderPinyin(sb, "old");
                    }
                    rCurr.XRenderSenses(sb, bodyChanged ? "new" : "");
                    if (bodyChanged)
                    {
                        rOld.XRenderSenses(sb, "old");
                    }
                    sb.AppendLine("</div>"); // <div class='entry'>
                }
            }
            sb.Append("</div>"); // <div class='changeEntry'>

            sb.Append("</div>"); // <div class='changeHead'>
            sb.Append("</div>"); // <div class='historyItem'>
            sb.AppendLine();

            if (trailingSeparator)
            {
                sb.AppendLine("<div class='historySep'></div>");
            }
        }
示例#8
0
        private static void renderPastChange(StringBuilder sb, CedictParser parser,
                                             ref string headNow, ref string trgNow, ref EntryStatus statusNow,
                                             ChangeItem ci, string lang)
        {
            sb.AppendLine("<div class='pastItem'>");

            sb.Append("<div class='changeSummary'>");
            sb.Append("<span class='changeType'>");
            sb.Append(HtmlEncoder.Default.Encode(getChangeTypeStr(ci.ChangeType, ci.CountB, statusNow, lang)));
            sb.Append(" &bull; </span>");
            sb.Append("<span class='changeUser'>");
            sb.Append(HtmlEncoder.Default.Encode(ci.User));
            sb.Append("</span>");
            sb.Append("<span class='changeTime'>");
            sb.Append(HtmlEncoder.Default.Encode(getTimeStr(ci.When, lang)));
            sb.Append("</span>");
            sb.AppendLine("</div>"); // <div class='changeSummary'>

            sb.AppendLine("<div class='changeNote'>");
            sb.Append("<span class='changeNoteText'>");

            if (ci.BulkRef != -1)
            {
                sb.Append("<span class='bulkLink'>[");
                sb.Append("<a href='/" + lang + "/read/details/change-" + ci.BulkRef.ToString("000") + "' target='_blank'>");
                sb.Append(TextProvider.Instance.GetString(lang, "history.bulkLink") + "</a>");
                sb.Append("]</span> ");
            }

            string note = HtmlEncoder.Default.Encode(ci.Note);

            note = note.Replace("&#xA;", "<br/>");
            sb.Append(note);
            sb.Append("</span>");
            sb.AppendLine("</div>"); // <div class='changeNote'>

            if (ci.HeadBefore != null)
            {
                CedictEntry eCurr         = parser.ParseEntry(headNow + " /x/", -1, null);
                CedictEntry eOld          = parser.ParseEntry(ci.HeadBefore + " /x/", -1, null);
                bool        simpChanged   = eCurr.ChSimpl != eOld.ChSimpl;
                bool        tradChanged   = eCurr.ChTrad != eOld.ChTrad;
                bool        pinyinChanged = CedictWriter.WritePinyin(eCurr) != CedictWriter.WritePinyin(eOld);
                // Render in parts
                sb.AppendLine("<div class='entry'>");
                // Let's not dim identical chars if anything changed in HW
                EntryRenderer rCurr = new EntryRenderer(lang, eCurr, !simpChanged && !tradChanged);
                EntryRenderer rOld  = new EntryRenderer(lang, eOld, !simpChanged && !tradChanged);
                rCurr.OneLineHanziLimit = rOld.OneLineHanziLimit = 12;
                if (simpChanged || tradChanged)
                {
                    rCurr.XRenderHanzi(sb, simpChanged ? "new" : "", tradChanged ? "new" : "");
                    rOld.XRenderHanzi(sb, simpChanged ? "old" : "", tradChanged ? "old" : "");
                }
                if (pinyinChanged)
                {
                    rCurr.XRenderPinyin(sb, pinyinChanged ? "new" : "");
                    rOld.XRenderPinyin(sb, "old");
                }
                sb.AppendLine("</div>"); // <div class='entry'>
                // Propagate change
                headNow = ci.HeadBefore;
            }

            if (ci.BodyBefore != null)
            {
                CedictEntry   entryNew = parser.ParseEntry("的 的 [de5] " + trgNow, -1, null);
                EntryRenderer er       = new EntryRenderer(lang, entryNew, true);
                er.XRenderSenses(sb, "new");
                CedictEntry entryOld = parser.ParseEntry("的 的 [de5] " + ci.BodyBefore, -1, null);
                er = new EntryRenderer(lang, entryOld, true);
                er.XRenderSenses(sb, "old");
                // Propagate change
                trgNow = ci.BodyBefore;
            }
            if (ci.StatusBefore != 99)
            {
                statusNow = (EntryStatus)ci.StatusBefore;
            }

            sb.AppendLine("</div>"); // <div class='pastItem'>
        }
示例#9
0
        public void Work()
        {
            string line;

            using (var fsDict = new FileStream("chdict.u8", FileMode.Open, FileAccess.Read))
                using (var srDict = new StreamReader(fsDict))
                    using (var fsDiag = new FileStream("chd-diag.txt", FileMode.Create, FileAccess.ReadWrite))
                        using (var swDiag = new StreamWriter(fsDiag))
                            using (var fsTrip = new FileStream("chd-trip.txt", FileMode.Create, FileAccess.ReadWrite))
                                using (var swTrip = new StreamWriter(fsTrip))
                                {
                                    while ((line = srDict.ReadLine()) != null)
                                    {
                                        ++lineNum;
                                        if (line.StartsWith("#"))
                                        {
                                            continue;
                                        }
                                        CedictEntry entry = parser.ParseEntry(line, lineNum, swDiag);
                                        if (entry != null)
                                        {
                                            string trippedLine = CedictWriter.Write(entry);
                                            if (trippedLine != line)
                                            {
                                                swTrip.WriteLine(line);
                                                swTrip.WriteLine(trippedLine);
                                            }
                                            fileHead(entry);
                                            countTags(entry);
                                            checkCommas(entry, lineNum, swDiag);
                                            countPrefixes(entry, swDiag);
                                            ++entryCount;
                                            senseCount += entry.SenseCount;
                                            countMeasureWords(entry);
                                        }
                                    }
                                    writeHeadIssues(swDiag);
                                    writePrefixes();
                                    List <TC> tlst = new List <TC>();
                                    foreach (var x in tags)
                                    {
                                        tlst.Add(new TC {
                                            Tag = x.Key, Count = x.Value
                                        });
                                    }
                                    tlst.Sort((x, y) => y.Count.CompareTo(x.Count));
                                    using (FileStream fsTags = new FileStream("chd-stats.txt", FileMode.Create, FileAccess.ReadWrite))
                                        using (StreamWriter sw = new StreamWriter(fsTags))
                                        {
                                            sw.WriteLine("ZH entries: " + entryCount);
                                            sw.WriteLine("HU senses: " + senseCount);
                                            sw.WriteLine("Entries with CL: " + entriesWithMW);
                                            sw.WriteLine();
                                            foreach (var x in tlst)
                                            {
                                                sw.WriteLine(x.Count + "\t" + x.Tag);
                                            }
                                            sw.WriteLine();
                                            List <string> mws = new List <string>();
                                            foreach (var x in simpMWCounts)
                                            {
                                                mws.Add(x.Key);
                                            }
                                            mws.Sort((x, y) => simpMWCounts[y].CompareTo(simpMWCounts[x]));
                                            foreach (string mw in mws)
                                            {
                                                sw.WriteLine(simpMWCounts[mw] + "\t" + mw);
                                            }
                                        }
                                }
        }
示例#10
0
 private void toVersions(List <HistRec> recs, out List <EntryVersion> history, out int entryId)
 {
     entryId = recs[0].EntryId;
     history = new List <EntryVersion>();
     // Sort records newest to oldest
     recs.Sort((x, y) => y.ModifTimeUtc.CompareTo(x.ModifTimeUtc));
     // Resolve HW, TRG and STATUS for each version
     string[]      verHw     = new string[recs.Count];
     string[]      verTrg    = new string[recs.Count];
     EntryStatus[] verStatus = new EntryStatus[recs.Count];
     for (int i = 0; i != recs.Count; ++i)
     {
         HistRec rec = recs[i];
         // Newest: take entry, "propagate" all the way to oldest
         if (i == 0)
         {
             for (int j = 0; j != recs.Count; ++j)
             {
                 verHw[j]     = rec.EntryHw;
                 verTrg[j]    = rec.EntryTrg;
                 verStatus[j] = rec.EntryStatus;
             }
         }
         // Change has "before" value: propagate to earlier versions
         if (rec.ModifHwBefore != null)
         {
             for (int j = i + 1; j < verHw.Length; ++j)
             {
                 verHw[j] = rec.ModifHwBefore;
             }
         }
         if (rec.ModifTrgBefore != null)
         {
             for (int j = i + 1; j < verTrg.Length; ++j)
             {
                 verTrg[j] = rec.ModifTrgBefore;
             }
         }
         if (rec.ModifStatusBefore != 99)
         {
             for (int j = i + 1; j < verStatus.Length; ++j)
             {
                 verStatus[j] = (EntryStatus)rec.ModifStatusBefore;
             }
         }
     }
     // Moving now from oldest to newest, build history
     // First and last item are special: they always contain entry
     // First coz we must "anchor" entry; last because it's always present in non-commented form
     for (int i = recs.Count - 1; i >= 0; --i)
     {
         HistRec      rec   = recs[i];
         CedictEntry  entry = parser.ParseEntry(verHw[i] + " " + verTrg[i], -1, null);
         EntryVersion ev    = new EntryVersion
         {
             Timestamp = rec.ModifTimeUtc,
             User      = idToUserName[rec.ModifUserId],
             Status    = verStatus[i],
             BulkRef   = rec.ModifBulkRef,
             Comment   = rec.ModifNote,
             Entry     = null,
         };
         // First and last version always get entry
         if (i == 0 || i == recs.Count - 1)
         {
             ev.Entry = entry;
         }
         // Also if HW or TRG changed from earlier (i + 1) version
         else if (verHw[i] != verHw[i + 1] || verTrg[i] != verTrg[i + 1])
         {
             ev.Entry = entry;
         }
         // Append to history
         history.Add(ev);
     }
 }
示例#11
0
        public void Work()
        {
            Random         rnd       = new Random(0);
            CedictParser   parser    = new CedictParser();
            HashSet <int>  idSet     = new HashSet <int>();
            StringBuilder  sb        = new StringBuilder();
            HashSet <char> simpChars = new HashSet <char>();

            using (FileStream fsIn = new FileStream("chdict.u8", FileMode.Open, FileAccess.Read))
                using (StreamReader sr = new StreamReader(fsIn))
                {
                    string line;
                    while ((line = sr.ReadLine()) != null)
                    {
                        if (line.StartsWith("#"))
                        {
                            continue;
                        }

                        int ix1 = line.IndexOf(" [");
                        int ix2 = line.IndexOf("] /");
                        line = line.Substring(0, ix1) + " [" + line.Substring(ix1 + 2, ix2 - ix1).ToLower() + line.Substring(ix2 + 2);

                        CedictEntry entry = parser.ParseEntry(line, 0, null);
                        if (entry == null)
                        {
                            continue;
                        }
                        if (entry.ChSimpl.Length > 16)
                        {
                            continue;
                        }

                        int id = rnd.Next();
                        while (idSet.Contains(id))
                        {
                            id = rnd.Next();
                        }
                        idSet.Add(id);
                        string strId = EntryId.IdToString(id);

                        sb.Clear();
                        // Line with ID
                        sb.AppendLine("# ID-" + strId);
                        // First version metainfo
                        string statStr = "Stat-Verif";
                        sb.AppendLine("# Ver 2017-05-02T22:41:05Z gabor " + statStr + " 001>CHDICT törzsanyag");
                        // The entry itself
                        sb.AppendLine(CedictWriter.Write(entry));

                        foreach (char c in entry.ChSimpl)
                        {
                            simpChars.Add(c);
                        }

                        items.Add(new ResItem {
                            ID = id, Lines = sb.ToString()
                        });
                    }
                }
        }
示例#12
0
        public IActionResult GetEditEntryData([FromQuery] string entryId, [FromQuery] string lang)
        {
            if (entryId == null || lang == null)
            {
                return(StatusCode(400, "Missing parameter(s)."));
            }

            // The data we'll return.
            EditEntryData res = new EditEntryData();

            // Is this an authenticated user?
            int    userId;
            string userName;

            auth.CheckSession(HttpContext.Request.Headers, out userId, out userName);
            // Can she approve entries?
            if (userId != -1)
            {
                res.CanApprove = auth.CanApprove(userId);
            }

            // Retrieve entry
            int         idVal = EntryId.StringToId(entryId);
            string      hw, trg;
            EntryStatus status;

            SqlDict.GetEntryById(idVal, out hw, out trg, out status);
            CedictParser parser = new CedictParser();
            CedictEntry  entry  = parser.ParseEntry(hw + " " + trg, 0, null);

            res.Status     = status.ToString().ToLowerInvariant();
            res.HeadSimp   = entry.ChSimpl;
            res.HeadTrad   = entry.ChTrad;
            res.HeadPinyin = "";
            for (int i = 0; i != entry.PinyinCount; ++i)
            {
                if (res.HeadPinyin.Length > 0)
                {
                    res.HeadPinyin += " ";
                }
                var pys = entry.GetPinyinAt(i);
                res.HeadPinyin += pys.GetDisplayString(false);
            }
            res.TrgTxt = trg.Trim('/').Replace('/', '\n').Replace('\\', '/');

            // Entry HTML
            entry.Status = status;
            EntryRenderer er = new EntryRenderer(lang, entry, true, "mainEntry");

            er.OneLineHanziLimit = 12;
            StringBuilder sb = new StringBuilder();

            er.Render(sb, null);
            res.EntryHtml = sb.ToString();

            // Entry history
            List <ChangeItem> changes = SqlDict.GetEntryChanges(idVal);

            sb.Clear();
            HistoryRenderer.RenderEntryChanges(sb, hw, trg, status, changes, lang);
            res.HistoryHtml = sb.ToString();

            return(new ObjectResult(res));
        }
示例#13
0
        private bool validateHeadword(string lang, string simp, string trad, string pinyin,
                                      List <HeadwordProblem> errorsSimp, List <HeadwordProblem> errorsTrad, List <HeadwordProblem> errorsPinyin)
        {
            var    tprov = TextProvider.Instance;
            string msg;

            // Check each simplified: is it really simplified?
            UniHanziInfo[] uhiSimp = langRepo.GetUnihanInfo(simp);
            for (int i = 0; i != uhiSimp.Length; ++i)
            {
                var uhi = uhiSimp[i];
                if (!uhi.CanBeSimp)
                {
                    msg = tprov.GetString(lang, "editEntry.hwProblemNotSimplified");
                    msg = string.Format(msg, simp[i]);
                    errorsSimp.Add(new HeadwordProblem(false, msg));
                }
            }
            // Check each traditional: is it really traditional?
            UniHanziInfo[] uhiTrad = langRepo.GetUnihanInfo(trad);
            for (int i = 0; i != uhiTrad.Length; ++i)
            {
                var uhi = uhiTrad[i];
                // Traditional chars are listed as their own traditional variant
                if (Array.IndexOf(uhi.TradVariants, trad[i]) < 0)
                {
                    msg = tprov.GetString(lang, "editEntry.hwProblemNotTraditional");
                    msg = string.Format(msg, trad[i]);
                    errorsTrad.Add(new HeadwordProblem(false, msg));
                }
            }
            // Check each traditional against its simplified friend
            if (trad.Length != simp.Length)
            {
                errorsTrad.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemSimpTradCounts")));
            }
            else
            {
                for (int i = 0; i != uhiSimp.Length; ++i)
                {
                    var uhi = uhiSimp[i];
                    if (Array.IndexOf(uhi.TradVariants, trad[i]) < 0)
                    {
                        msg = tprov.GetString(lang, "editEntry.hwProblemNotTradForSimp");
                        msg = string.Format(msg, simp[i], trad[i]);
                        errorsTrad.Add(new HeadwordProblem(false, msg));
                    }
                }
            }
            // Normalize pinyin (multiple spaces, leading/trailing spaces)
            string pyNorm = pinyin;

            while (true)
            {
                string x = pyNorm.Replace("  ", " ");
                if (x == pyNorm)
                {
                    break;
                }
                pyNorm = x;
            }
            pyNorm = pyNorm.Trim();
            if (pyNorm != pinyin)
            {
                errorsPinyin.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemExtraSpacesPinyin")));
            }
            // Try to match up normalized pinyin with simplified Hanzi
            CedictParser parser = new CedictParser();
            CedictEntry  ee     = null;

            try { ee = parser.ParseEntry(trad + " " + simp + " [" + pyNorm + "] /x/", 0, null); }
            catch { }
            if (ee == null)
            {
                errorsPinyin.Add(new HeadwordProblem(true, tprov.GetString(lang, "editEntry.hwProblemInvalidPinyin")));
            }
            else
            {
                if (simp.Length == ee.ChSimpl.Length)
                {
                    for (int i = 0; i != uhiSimp.Length; ++i)
                    {
                        var uhi = uhiSimp[i];
                        var py  = ee.GetPinyinAt(i);
                        var cnt = uhi.Pinyin.Count(x => x.GetDisplayString(false) == py.GetDisplayString(false));
                        if (cnt == 0)
                        {
                            msg = tprov.GetString(lang, "editEntry.hwProblemWrongPinyin");
                            msg = string.Format(msg, py.GetDisplayString(false), simp[i]);
                            errorsPinyin.Add(new HeadwordProblem(false, msg));
                        }
                    }
                }
            }
            return(ee != null);
        }
示例#14
0
        public IActionResult GetEntryPreview([FromQuery] string origHw,
                                             [FromQuery] string trad, [FromQuery] string simp, [FromQuery] string pinyin,
                                             [FromQuery] string trgTxt, [FromQuery] string lang)
        {
            if (origHw == null || trgTxt == null || lang == null)
            {
                return(StatusCode(400, "Missing parameter(s)."));
            }
            if (trad == null)
            {
                trad = "";
            }
            if (simp == null)
            {
                simp = "";
            }
            if (pinyin == null)
            {
                pinyin = "";
            }
            EditEntryPreviewResult res = new EditEntryPreviewResult();

            // Ugly try-catch, but some incorrect input just generates an exception.
            // We still want to return a meaningful "no preview" response.
            try
            {
                // DBG
                if (trgTxt.Contains("micu-barf"))
                {
                    throw new Exception("barf");
                }

                // Validate current headword
                bool hwParses = validateHeadword(lang, simp, trad, pinyin,
                                                 res.ErrorsSimp, res.ErrorsTrad, res.ErrorsPinyin);

                trgTxt = trgTxt.Replace("\r\n", "\n");
                trgTxt = trgTxt.Replace('/', '\\');
                trgTxt = trgTxt.Replace('\n', '/');
                trgTxt = "/" + trgTxt + "/";

                // Headword: use original if current headword has errors
                string hw = trad + " " + simp + " [" + pinyin + "]";
                if (!hwParses)
                {
                    hw = origHw;
                }

                CedictParser parser = new CedictParser();
                CedictEntry  entry  = parser.ParseEntry(hw + " " + trgTxt, 0, null);
                if (entry != null)
                {
                    EntryRenderer er = new EntryRenderer(lang, entry, true, "mainEntry");
                    er.OneLineHanziLimit = 12;
                    StringBuilder sb = new StringBuilder();
                    er.Render(sb, null);
                    res.PreviewHtml = sb.ToString();
                }
            }
            catch { }
            return(new ObjectResult(res));
        }