示例#1
0
        public string FindDeck(string value)
        {
            // if searching for all decks, skip
            if (value.Equals("*"))
            {
                return("skip");
                // deck types
            }
            else if (value.Equals("filtered"))
            {
                return("c.odid");
            }
            List <long> ids = null;

            // current deck?
            if (value.Equals("current", StringComparison.OrdinalIgnoreCase))
            {
                ids = GetChildDeckIds((long)JsonHelper.GetNameNumber(collection.Deck.Current(), "id"));
            }
            else if (!value.Contains("*"))
            {
                // single deck
                ids = GetChildDeckIds(collection.Deck.AddOrResuedDeck(value, false));
            }
            else
            {
                // wildcard
                ids   = new List <long>();
                value = value.Replace("*", ".*");
                value = value.Replace("+", "\\+");
                foreach (JsonObject d in collection.Deck.All())
                {
                    if (Regex.IsMatch(d.GetNamedString("name"), "(?i)" + value))
                    {
                        foreach (long id in GetChildDeckIds((long)JsonHelper.GetNameNumber(d, "id")))
                        {
                            if (!ids.Contains(id))
                            {
                                ids.Add(id);
                            }
                        }
                    }
                }
            }
            if (ids == null || ids.Count == 0)
            {
                return(null);
            }
            string sids = Utils.Ids2str(ids.ToArray());

            return("c.did in " + sids + " or c.odid in " + sids);
        }
示例#2
0
        public List <long> DeckIdsForConf(long confId)
        {
            List <long> dids = new List <long>();

            foreach (JsonObject deck in deckDict.Values)
            {
                if (deck.ContainsKey("conf") && (JsonHelper.GetNameNumber(deck, "conf") == confId))
                {
                    dids.Add((long)JsonHelper.GetNameNumber(deck, "id"));
                }
            }
            return(dids);
        }
示例#3
0
        private string FindModel(string value)
        {
            LinkedList <long> ids = new LinkedList <long>();

            foreach (JsonObject m in collection.Models.All())
            {
                if (m.GetNamedString("name").Equals(value, StringComparison.OrdinalIgnoreCase))
                {
                    ids.AddLast((long)JsonHelper.GetNameNumber(m, "id"));
                }
            }
            return("n.mid in " + Utils.Ids2str(ids.ToArray()));
        }
示例#4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="jObj">Json Deck to rename</param>
        /// <param name="newName">New name</param>
        /// <param name="isNeedAddToActive">Is need to add to active deck after rename</param>
        public string Rename(JsonObject jObj, string newName, bool isNeedAddToActive = true)
        {
            //Different with java and python ver, we don't throw exception here and only add "_"
            //Check for unique name should be done in other function
            //This is just the last check to ensure we never create a deck with the same name
            while (AllNames().Contains(newName))
            {
                newName += "_";
            }

            newName = EnsureParents(newName);

            // make sure we're not nesting under a filtered deck
            if (newName.Contains(Constant.SUBDECK_SEPERATE))
            {
                string[] parts    = newName.Split(new string[] { Constant.SUBDECK_SEPERATE }, StringSplitOptions.None);
                string[] subParts = new string[parts.Length - 1];
                Array.Copy(parts, subParts, subParts.Length);
                string newParent = String.Join(Constant.SUBDECK_SEPERATE, subParts);
                if (JsonHelper.GetNameNumber(GetDeckByName(newParent), "dyn") != 0)
                {
                    throw new DeckRenameException(DeckRenameException.ErrorCode.FILTERED_NOSUBDEKCS);
                }
            }

            //Rename children
            string oldName = jObj.GetNamedString("name");
            string str;

            foreach (JsonObject grp in All())
            {
                if (grp.GetNamedString("name").StartsWith(oldName + Constant.SUBDECK_SEPERATE))
                {
                    str         = grp.GetNamedString("name").ReplaceFirst(oldName + Constant.SUBDECK_SEPERATE, newName + Constant.SUBDECK_SEPERATE);
                    grp["name"] = JsonValue.CreateStringValue(str);
                    Save(grp);
                }
            }
            //adjust name
            jObj["name"] = JsonValue.CreateStringValue(newName);
            // ensure we have parents again, as we may have renamed parent->child
            newName = EnsureParents(newName);
            Save(jObj);
            // renaming may have altered active deckId order
            if (isNeedAddToActive)
            {
                MaybeAddToActive();
            }

            return(newName);
        }
示例#5
0
        public void RestoreToDefault(JsonObject conf)
        {
            int        oldOrder = (int)JsonHelper.GetNameNumber(conf.GetNamedObject("new"), "order");
            JsonObject temp     = JsonObject.Parse(defaultConf);

            temp.Add("id", conf.GetNamedValue("id"));
            temp.Add("name", conf.GetNamedValue("name"));
            deckConf.Add((long)JsonHelper.GetNameNumber(conf, "id"), temp);
            Save(temp);
            // if it was previously randomized, resort
            if (oldOrder == 0)
            {
                collection.Sched.ResortConf(temp);
            }
        }
示例#6
0
        private static string Limit(Collection collection)
        {
            if (IsWholeCollection)
            {
                List <long> ids = new List <long>();
                foreach (JsonObject d in collection.Deck.All())
                {
                    ids.Add((long)JsonHelper.GetNameNumber(d, "id"));
                }

                return(Utils.Ids2str(ids));
            }
            else
            {
                return(collection.Sched.DeckLimit());
            }
        }
示例#7
0
        public Dictionary <string, long> Children(long did)
        {
            string name;

            name = Get(did).GetNamedString("name");
            Dictionary <string, long> actv = new Dictionary <string, long>();

            foreach (JsonObject g in All())
            {
                string deckName = g.GetNamedString("name");
                if (deckName.StartsWith(name + Constant.SUBDECK_SEPERATE))
                {
                    actv[deckName] = (long)JsonHelper.GetNameNumber(g, "id");
                }
            }
            return(actv);
        }
示例#8
0
        private string FindTemplate(string value)
        {
            // were we given an ordinal number?
            int?num = null;

            try
            {
                num = int.Parse(value) - 1;
            }
            catch (FormatException)
            {
                num = null;
            }
            if (num != null)
            {
                return("c.ord = " + num);
            }
            // search for template names
            List <string> lims = new List <string>();

            foreach (JsonObject m in collection.Models.All())
            {
                JsonArray tmpls = m.GetNamedArray("tmpls");
                for (uint ti = 0; ti < tmpls.Count; ++ti)
                {
                    JsonObject t = tmpls.GetObjectAt(ti);
                    if (t.GetNamedString("name").Equals(value, StringComparison.OrdinalIgnoreCase))
                    {
                        if (JsonHelper.GetNameNumber(m, "type") == (double)ModelType.CLOZE)
                        {
                            // if the user has asked for a cloze card, we want
                            // to give all ordinals, so we just limit to the
                            // model instead
                            lims.Add("(n.mid = " + (long)JsonHelper.GetNameNumber(m, "id") + ")");
                        }
                        else
                        {
                            lims.Add("(n.mid = " + (long)JsonHelper.GetNameNumber(m, "id") + " and c.ord = " +
                                     (int)JsonHelper.GetNameNumber(t, "ord") + ")");
                        }
                    }
                }
            }
            return(String.Join(" or ", lims.ToArray()));
        }
示例#9
0
        public JsonObject ConfForDeckId(long did)
        {
            JsonObject deck = Get(did, false);

            if (deck == null)
            {
                throw new DeckNotFoundException();
            }

            if (deck.ContainsKey("conf"))
            {
                JsonObject conf = GetConf((long)JsonHelper.GetNameNumber(deck, "conf"));
                conf["dyn"] = JsonValue.CreateNumberValue(0);
                return(conf);
            }
            // dynamic decks have embedded conf
            return(deck);
        }
示例#10
0
        public void Remove(long deckId, bool cardsToo = false, bool childrenToo = true)
        {
            JsonObject deck;

            if (deckId == 1)
            {
                // we won't allow the default deck to be deleted, but if it's a
                // child of an existing deck then it needs to be renamed
                deck = Get(deckId);
                if (deck.GetNamedString("name").Contains(Constant.SUBDECK_SEPERATE))
                {
                    deck["name"] = JsonValue.CreateStringValue("Default");
                    Save(deck);
                }
                return;
            }

            // log the removal regardless of whether we have the deck or not
            collection.LogRem(new long[] { deckId }, RemovalType.DECK);

            if (!deckDict.ContainsKey(deckId))
            {
                return;
            }

            deck = Get(deckId);
            if (JsonHelper.GetNameNumber(deck, "dyn") != 0)
            {
                // deleting a cramming deck returns cards to their previous deck
                // rather than deleting the cards
                collection.Sched.EmptyDyn(deckId);
                RemoveIfChildrenToo(deckId, childrenToo, cardsToo);
            }
            else
            {
                RemoveIfChildrenToo(deckId, childrenToo, cardsToo);
                RemoveIfNoteAndCardsToo(deckId, cardsToo);
            }

            deckDict.Remove(deckId);
            EnsureHaveActiveDeck(deckId);
            Save();
        }
示例#11
0
        public JsonObject GetTemplate()
        {
            JsonObject m = GetModel();

            if (JsonHelper.GetNameNumber(m, "type") == (double)ModelType.STD)
            {
                try
                {
                    return(m.GetNamedArray("tmpls").GetObjectAt((uint)ord));
                }
                catch
                {   //This should only happen if user changes this card note type from cloze to standard
                    //and the note of this card contains more than one cloze
                    return(GetModel().GetNamedArray("tmpls").GetObjectAt(0));
                }
            }
            else
            {
                return(GetModel().GetNamedArray("tmpls").GetObjectAt(0));
            }
        }
示例#12
0
        public List <string> FileNameInMediaFolder(long mid, string strIn, bool includeRemote = false)
        {
            List <string> returnList = new List <string>();
            List <string> stringList = new List <string>();
            JsonObject    model      = collection.Models.Get(mid);

            int type = (int)JsonHelper.GetNameNumber(model, "type");

            if ((type == (int)ModelType.CLOZE) && strIn.Contains("{{c"))
            {
                stringList = ExpandClozes(strIn);
            }
            else
            {
                stringList.Add(strIn);
            }

            string str;

            foreach (string s in stringList)
            {
                str = LaTeX.MungeQA(s, collection);
                MatchCollection matches;
                foreach (Regex p in RegExps)
                {
                    matches = p.Matches(str);
                    foreach (Match m in matches)
                    {
                        string fName   = m.Groups["fname"].Value;
                        bool   isLocal = !remoteRegex.IsMatch(fName.ToLowerInvariant());
                        if (isLocal || includeRemote)
                        {
                            returnList.Add(fName);
                        }
                    }
                }
            }
            return(returnList);
        }
示例#13
0
        /// <summary>
        /// An unsorted list of all deck names.
        /// </summary>
        /// <param name="dyn"></param>
        /// <returns></returns>
        public List <string> AllNames(bool dyn = true)
        {
            List <string> list = new List <string>();

            if (dyn)
            {
                foreach (JsonObject x in deckDict.Values)
                {
                    list.Add(x.GetNamedString("name"));
                }
            }
            else
            {
                foreach (JsonObject x in deckDict.Values)
                {
                    if (JsonHelper.GetNameNumber(x, "dyn") == 0)
                    {
                        list.Add(x.GetNamedString("name"));
                    }
                }
            }
            return(list);
        }
示例#14
0
 private static void Upgrade(Collection col, int ver)
 {
     if (ver < 3)
     {
         // new deck properties
         foreach (JsonObject d in col.Deck.All())
         {
             d["dyn"]       = JsonValue.CreateNumberValue(0);
             d["collapsed"] = JsonValue.CreateBooleanValue(false);
             col.Deck.Save(d);
         }
     }
     if (ver < 4)
     {
         col.ModSchemaNoCheck();
         List <JsonObject> clozes = new List <JsonObject>();
         foreach (JsonObject m in col.Models.All())
         {
             if (!m.GetNamedArray("tmpls").GetObjectAt(0).GetNamedString("qfmt").Contains("{{cloze:"))
             {
                 m["type"] = JsonValue.CreateNumberValue((int)ModelType.STD);
             }
             else
             {
                 clozes.Add(m);
             }
         }
         foreach (JsonObject m in clozes)
         {
             UpgradeClozeModel(col, m);
         }
         col.Database.Execute("UPDATE col SET ver = 4");
     }
     if (ver < 5)
     {
         col.Database.Execute("UPDATE cards SET odue = 0 WHERE queue = 2");
         col.Database.Execute("UPDATE col SET ver = 5");
     }
     if (ver < 6)
     {
         col.ModSchemaNoCheck();
         foreach (JsonObject m in col.Models.All())
         {
             m["css"] = JsonObject.Parse(Models.defaultModel).GetNamedValue("css");
             JsonArray ar = m.GetNamedArray("tmpls");
             for (uint i = 0; i < ar.Count; i++)
             {
                 JsonObject t = ar.GetObjectAt(i);
                 if (!t.ContainsKey("css"))
                 {
                     continue;
                 }
                 m["css"] = JsonValue.CreateStringValue(
                     m.GetNamedString("css") + "\n"
                     + t.GetNamedString("css").Replace(".card ", ".card" + t.GetNamedString("ord") + 1));
                 t.Remove("css");
             }
             col.Models.Save(m);
         }
         col.Database.Execute("UPDATE col SET ver = 6");
     }
     if (ver < 7)
     {
         col.ModSchemaNoCheck();
         col.Database.Execute("UPDATE cards SET odue = 0 WHERE (type = 1 OR queue = 2) AND NOT odid");
         col.Database.Execute("UPDATE col SET ver = 7");
     }
     if (ver < 8)
     {
         col.ModSchemaNoCheck();
         col.Database.Execute("UPDATE cards SET due = due / 1000 WHERE due > 4294967296");
         col.Database.Execute("UPDATE col SET ver = 8");
     }
     if (ver < 9)
     {
         col.Database.Execute("UPDATE col SET ver = 9");
     }
     if (ver < 10)
     {
         col.Database.Execute("UPDATE cards SET left = left + left * 1000 WHERE queue = 1");
         col.Database.Execute("UPDATE col SET ver = 10");
     }
     if (ver < 11)
     {
         col.ModSchemaNoCheck();
         foreach (JsonObject d in col.Deck.All())
         {
             if (JsonHelper.GetNameNumber(d, "dyn") != 0)
             {
                 int order = (int)JsonHelper.GetNameNumber(d, "order");
                 // failed order was removed
                 if (order >= 5)
                 {
                     order -= 1;
                 }
                 JsonArray ja = new JsonArray();
                 ja.Add(d.GetNamedValue("search"));
                 ja.Add(d.GetNamedValue("limit"));
                 ja.Add(JsonValue.CreateNumberValue(order));
                 d.Add("terms", new JsonArray());
                 d.GetNamedArray("terms").Insert(0, ja);
                 d.Remove("search");
                 d.Remove("limit");
                 d.Remove("order");
                 d["resched"] = JsonValue.CreateBooleanValue(true);
                 d["return"]  = JsonValue.CreateBooleanValue(true);
             }
             else
             {
                 if (!d.ContainsKey("extendNew"))
                 {
                     d["extendNew"] = JsonValue.CreateNumberValue(10);
                     d["extendRev"] = JsonValue.CreateNumberValue(50);
                 }
             }
             col.Deck.Save(d);
         }
         foreach (JsonObject c in col.Deck.AllConf())
         {
             JsonObject r = c.GetNamedObject("rev");
             r["ivlFct"] = JsonValue.CreateNumberValue(JsonHelper.GetNameNumber(r, "ivlFct", 1));
             if (r.ContainsKey("ivlfct"))
             {
                 r.Remove("ivlfct");
             }
             r["maxIvl"] = JsonValue.CreateNumberValue(36500);
             col.Deck.Save(c);
         }
         foreach (JsonObject m in col.Models.All())
         {
             JsonArray tmpls = m.GetNamedArray("tmpls");
             for (uint ti = 0; ti < tmpls.Count; ++ti)
             {
                 JsonObject t = tmpls.GetObjectAt(ti);
                 t["bqfmt"] = JsonValue.CreateStringValue("");
                 t["bafmt"] = JsonValue.CreateStringValue("");
             }
             col.Models.Save(m);
         }
         col.Database.Execute("update col set ver = 11");
     }
 }
示例#15
0
        private string FindField(string field, string val)
        {
            //We need two expressions to query the cards: One that will use REGEX syntax and another
            //that should use SQLITE LIKE clause syntax.
            string sqlVal = val
                            .Replace("%", "\\%") // For SQLITE, we escape all % signs
                            .Replace("*", "%");  // And then convert the * into non-escaped % signs


            //The following three lines make sure that only _ and * are valid wildcards.
            string regexVal = Regex.Escape(sqlVal).Replace("\\_", ".").Replace("%", ".*");

            //For the pattern, we use the javaVal expression that uses REGEX syntax
            //Regex pattern = new Regex("(?s)\\Q" + regexVal + "\\E", RegexOptions.Compiled | RegexOptions.IgnoreCase);
            Regex pattern = new Regex("(?s)^" + regexVal + "$", RegexOptions.Compiled | RegexOptions.IgnoreCase);

            // find models that have that field
            Dictionary <long, object[]> mods = new Dictionary <long, object[]>();

            foreach (JsonObject m in collection.Models.All())
            {
                JsonArray flds = m.GetNamedArray("flds");
                for (uint fi = 0; fi < flds.Count; ++fi)
                {
                    JsonObject f = flds.GetObjectAt(fi);
                    if (f.GetNamedString("name").Equals(field, StringComparison.OrdinalIgnoreCase))
                    {
                        mods.Add((long)JsonHelper.GetNameNumber(m, "id"), new object[] { m, JsonHelper.GetNameNumber(f, "ord") });
                    }
                }
            }
            if (mods.Count == 0)
            {
                // nothing has that field
                return(null);
            }

            LinkedList <long> nids = new LinkedList <long>();
            // Here we use the sqlVal expression, that is required for LIKE syntax in sqllite.
            // There is no problem with special characters, because only % and _ are special
            // characters in this syntax.
            var list = collection.Database.QueryColumn <NoteTable>(
                "select id, mid, flds from notes where mid in " +
                Utils.Ids2str(mods.Keys.ToArray()) +
                " and flds like ? escape '\\'", new string[] { "%" + sqlVal + "%" });

            foreach (NoteTable n in list)
            {
                string[] flds = Utils.SplitFields(n.Fields);
                int      ord  = Convert.ToInt32(mods[n.Mid][1]);
                string   strg = flds[ord];
                if (pattern.IsMatch(strg))
                {
                    nids.AddLast(n.Id);
                }
            }
            if (nids.Count == 0)
            {
                return("0");
            }
            return("n.id in " + Utils.Ids2str(nids.ToArray()));
        }
示例#16
0
        public static int FindReplace(Collection collection, List <long> nids, string src, string dst, bool isRegex, string field, bool fold)
        {
            Dictionary <long, int> mmap = new Dictionary <long, int>();

            if (field != null)
            {
                foreach (JsonObject m in collection.Models.All())
                {
                    JsonArray flds = m.GetNamedArray("flds");
                    for (uint fi = 0; fi < flds.Count; ++fi)
                    {
                        JsonObject f = flds.GetObjectAt(fi);
                        if (f.GetNamedString("name").Equals(field))
                        {
                            mmap.Add((long)JsonHelper.GetNameNumber(m, "id"), (int)JsonHelper.GetNameNumber(f, "ord"));
                        }
                    }
                }
                if (mmap.Count == 0)
                {
                    return(0);
                }
            }
            // find and gather replacements
            if (!isRegex)
            {
                src = Regex.Escape(src);
            }
            if (fold)
            {
                src = "(?i)" + src;
            }
            Regex regex = new Regex(src, RegexOptions.Compiled);

            List <object[]> d     = new List <object[]>();
            string          snids = Utils.Ids2str(nids);

            nids = new List <long>();

            var list = collection.Database.QueryColumn <NoteTable>("select id, mid, flds from notes where id in " + snids);

            foreach (NoteTable n in list)
            {
                string flds     = n.Fields;
                string origFlds = flds;
                // does it match?
                string[] sflds = Utils.SplitFields(flds);
                if (field != null)
                {
                    long mid = n.Mid;
                    if (!mmap.ContainsKey(mid))
                    {
                        // note doesn't have that field
                        continue;
                    }
                    int ord = mmap[mid];
                    sflds[ord] = regex.Replace(sflds[ord], dst);
                }
                else
                {
                    for (int i = 0; i < sflds.Length; ++i)
                    {
                        sflds[i] = regex.Replace(sflds[i], dst);
                    }
                }
                flds = Utils.JoinFields(sflds);
                if (!flds.Equals(origFlds))
                {
                    long nid = n.Id;
                    nids.Add(nid);
                    d.Add(new object[] { flds, DateTimeOffset.Now.ToUnixTimeSeconds(), collection.Usn, nid }); // order based on query below
                }
            }

            if (d.Count == 0)
            {
                return(0);
            }
            // replace
            collection.Database.ExecuteMany("update notes set flds=?,mod=?,usn=? where id=?", d);
            long[] pnids = nids.ToArray();
            collection.UpdateFieldCache(pnids);
            collection.GenCards(pnids);
            return(d.Count);
        }
示例#17
0
        public List <long> DeckIdsForConf(JsonObject conf)
        {
            long confId = (long)JsonHelper.GetNameNumber(conf, "id");

            return(DeckIdsForConf(confId));
        }
示例#18
0
 public void UpdateConf(JsonObject jObj)
 {
     deckConf[(long)JsonHelper.GetNameNumber(jObj, "id")] = jObj;
     Save();
 }
示例#19
0
 public void Update(JsonObject jObj)
 {
     deckDict[(long)JsonHelper.GetNameNumber(jObj, "id")] = jObj;
     MaybeAddToActive();
     Save();
 }
示例#20
0
        /// <summary>
        /// Time limit for answering in milliseconds
        /// </summary>
        /// <returns></returns>
        public int TimeLimit()
        {
            JsonObject conf = collection.Deck.ConfForDeckId(oDid == 0 ? deckId : oDid);

            return((int)JsonHelper.GetNameNumber(conf, "maxTaken") * 1000);
        }
示例#21
0
 public long Selected()
 {
     return((long)JsonHelper.GetNameNumber(collection.Conf, "curDeck"));
 }
示例#22
0
 public bool IsDyn(long did)
 {
     return(JsonHelper.GetNameNumber(Get(did), "dyn") != 0);
 }
示例#23
0
        public bool ShowTimer()
        {
            var conf = collection.Deck.ConfForDeckId(oDid == 0 ? deckId : oDid);

            return(JsonHelper.GetNameNumber(conf, "timer", 1) != 0);
        }
示例#24
0
        public bool ShouldShowTimer()
        {
            var deck = collection.Deck.ConfForDeckId(oDid == 0 ? deckId : oDid);

            return(JsonHelper.GetNameNumber(deck, "timer") != 0);
        }