Tamer entity
Inheritance: BaseEntity
        protected override bool GetMercenaryInfo(ref Digimon digimon, Tamer tamer)
        {
            //we don't need starters info
            if (digimon.Type.IsStarter) {
                return false;
            }
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining detailed data of digimon \"{0}\" for tamer \"{1}\"", digimon.Name, tamer.Name);
            }

            string html = DownloadContent(string.Format(STR_URL_MERC_SIZE_RANK, tamer.Name, tamer.Guild.Server.Identifier, digimon.Type.Code));
            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);

            HtmlNode partnerNode;
            try {
                partnerNode = doc.DocumentNode.SelectNodes("//table[@class='forum_list']")[1].SelectSingleNode(".//tbody//tr[not(@onmouseover)]");
            } catch {
                return false;
            }

            if (partnerNode != null) {
                digimon.SizeRank = Convert.ToInt32(ClearStr(partnerNode.SelectSingleNode(".//td[1]").InnerText));
                digimon.Name = ClearStr(partnerNode.SelectSingleNode(".//td[2]//label").InnerText);
                Regex r = new Regex(STR_DIGIMON_SIZE, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                Match m = r.Match(partnerNode.SelectSingleNode(".//td[3]").InnerHtml);
                if (m.Success) {
                    digimon.SizeCm = Convert.ToInt32(m.Groups[1].ToString());
                    digimon.SizePc = Convert.ToInt32(m.Groups[3].ToString());
                    return true;
                }
            }
            return false;
        }
        protected override bool GetStarterInfo(ref Digimon digimon, Tamer tamer)
        {
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining starter digimon for tamer \"{0}\"", tamer.Name);
            }
            HtmlDocument doc = new HtmlDocument();
            string html = DownloadContent(string.Format(STR_URL_STARTER_RANK, tamer.Name, tamer.Guild.Server.Identifier));
            doc.LoadHtml(html);

            HtmlNode partnerNode;
            try {
                partnerNode = doc.DocumentNode.SelectNodes("//table[@class='forum_list']")[1].SelectSingleNode(".//tbody//tr[not(@onmouseover)]");
            } catch {
                return false;
            }

            if (partnerNode != null) {
                digimon.Rank = CheckRankNode(partnerNode.SelectSingleNode(".//td[1]"));
                digimon.Name = ClearStr(partnerNode.SelectSingleNode(".//td[2]//label").InnerText);
                digimon.Level = Convert.ToByte(ClearStr(partnerNode.SelectSingleNode(".//td[3]").InnerText));
            }
            return partnerNode != null;
        }
        protected override List<Digimon> GetDigimons(Tamer tamer, bool isDetailed)
        {
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining digimons for tamer \"{0}\"", tamer.Name);
            }
            List<Digimon> digimonList = new List<Digimon>();
            HtmlDocument doc = new HtmlDocument();

            string html = DownloadContent(string.Format(STR_URL_TAMER_POPPAGE, tamer.AccountId, tamer.Guild.Server.Identifier));
            doc.LoadHtml(html);

            //getting starter
            Digimon partner;
            try {
                partner = new Digimon() {
                    Tamer = tamer,
                    Name = ClearStr(doc.DocumentNode.SelectSingleNode("//div[1]//div[2]//div[2]//table[1]//tr[1]//td[2]//table[1]//tr[3]//td[2]//b").InnerText),
                    SizePc = 100
                };
            } catch {
                return digimonList;
            }

            DigimonType type = null;
            using (IDatabaseContext context = DatabaseManager.CreateContext()) {
                type = context.FindDigimonTypeBySearchKDMO(context.PrepareDigimonSearch(partner.Name));
            }
            if (type != null) {
                partner.Type = type;
                partner.Name = type.Name;
                partner.SizeCm = type.SizeCm;
            }
            digimonList.Add(partner);
            if (!GetStarterInfo(ref partner, tamer)) {
                if (LogManager != null) {
                    LogManager.ErrorFormat("Unable to obtain info about starter digimon \"{0}\" for tamer \"{1}\"", partner.Name, tamer.Name);
                }
            }

            HtmlNode mercList = doc.DocumentNode.SelectNodes("//table[@class='list']")[1];
            HtmlNodeCollection dlist = mercList.SelectNodes(".//tr");

            if (dlist != null) {
                using (IDatabaseContext context = DatabaseManager.CreateContext()) {
                    for (int i = 1; i < dlist.Count; i++) {
                        Digimon digimonInfo = new Digimon() {
                            Tamer = tamer,
                            Name = ClearStr(dlist[i].SelectSingleNode(".//td[1]").InnerText),
                            Level = Convert.ToByte(ClearStr(dlist[i].SelectSingleNode(".//td[2]//label").InnerText))
                        };

                        string rank = string.Empty;
                        foreach (char c in ClearStr(dlist[i].SelectSingleNode(".//td[3]//label").InnerText)) {
                            if (Char.IsDigit(c)) {
                                rank += c;
                            } else {
                                break;
                            }
                        }
                        digimonInfo.Rank = Convert.ToInt32(rank);
                        digimonInfo.Type = context.FindDigimonTypeBySearchKDMO(context.PrepareDigimonSearch(digimonInfo.Name));
                        if (digimonInfo.Type == null) {
                            continue;
                        }
                        digimonInfo.Name = digimonInfo.Type.Name;
                        digimonInfo.SizeCm = digimonInfo.Type.SizeCm;

                        if (digimonList.Count(d => d.Type.Equals(digimonInfo.Type)) == 0) {
                            if (isDetailed) {
                                if (!GetMercenaryInfo(ref digimonInfo, tamer)) {
                                    if (LogManager != null) {
                                        LogManager.ErrorFormat("Unable to obtain detailed data of digimon \"{0}\" for tamer \"{1}\"", digimonInfo.Name, tamer.Name);
                                    }
                                }
                            }
                            digimonList.Add(digimonInfo);
                            if (LogManager != null) {
                                LogManager.InfoFormat("Found digimon \"{0}\"", digimonInfo.Name);
                            }
                        }
                    }
                }
            }
            return digimonList;
        }
        protected override bool GetGuildInfo(ref Guild guild, bool isDetailed)
        {
            List<Tamer> tamerList = new List<Tamer>();
            HtmlDocument doc = new HtmlDocument();
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining info of {0}", guild.Name);
            }
            string html = DownloadContent(string.Format(STR_URL_GUILD_PAGE, guild.Identifier, "srv" + guild.Server.Identifier));
            doc.LoadHtml(html);

            HtmlNode ranking = doc.DocumentNode.SelectNodes("//table[@class='forum_list']//tbody")[1];
            HtmlNodeCollection tlist = ranking.SelectNodes(".//tr");
            if (tlist != null) {
                using (IDatabaseContext context = DatabaseManager.CreateContext()) {
                    for (int i = 0; i < tlist.Count; i++) {
                        try {
                            Tamer tamer = new Tamer() {
                                Guild = guild,
                                Name = ClearStr(tlist[i].SelectSingleNode(".//td[3]").InnerText),
                                Rank = CheckRankNode(tlist[i].SelectSingleNode(".//td[2]"))
                            };
                            OnStatusChanged(DMODownloadStatusCode.GETTING_TAMER, tamer.Name, i, tlist.Count);

                            Regex regex = new Regex(STR_TAMER_TYPE_REGEX, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                            Match match = regex.Match(tlist[i].SelectSingleNode(".//td[3]").InnerHtml);
                            if (match.Success) {
                                tamer.Type = context.FindTamerTypeByCode(Convert.ToInt32(match.Groups[2].ToString()));
                            }

                            regex = new Regex(STR_TAMER_LVL_REGEX, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                            match = regex.Match(tlist[i].SelectSingleNode(".//td[4]").InnerHtml);
                            if (match.Success) {
                                tamer.Level = Convert.ToByte(match.Groups[2].ToString());
                            }

                            regex = new Regex(STR_TAMER_ID_REGEX, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                            match = regex.Match(tlist[i].SelectSingleNode(".//td[7]").InnerHtml);
                            if (match.Success) {
                                tamer.AccountId = Convert.ToInt32(match.Groups[2].ToString());
                            }

                            if (tamer.Level != 0 && tamer.AccountId != 0) {
                                tamer.Digimons = GetDigimons(tamer, isDetailed);
                                if (tamer.Digimons.Count == 0) {
                                    return false;
                                }
                                Digimon partner = tamer.Digimons.FirstOrDefault(d => d.Type.IsStarter);
                                if (partner != null) {
                                    partner.Name = ClearStr(tlist[i].SelectSingleNode(".//td[5]").InnerText);
                                }
                                tamerList.Add(tamer);
                                if (LogManager != null) {
                                    LogManager.InfoFormat("Found tamer \"{0}\"", tamer.Name);
                                }
                            }
                        } catch {
                        }
                    }
                }
            }

            if (tamerList.Count == 0) {
                return false;
            }
            guild.Tamers = tamerList;
            return true;
        }
        protected override bool GetMercenaryInfo(ref Digimon digimon, Tamer tamer)
        {
            //we don't need starters info
            if (digimon.Type.IsStarter) {
                return false;
            }
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining detailed data of digimon \"{0}\" for tamer \"{1}\"", digimon.Name, tamer.Name);
            }

            HtmlNode ranking = tryLoadNode(string.Format(STR_URL_MERC_SIZE_RANK, tamer.Name, "srv" + tamer.Guild.Server.Identifier.ToString(), digimon.Type.Code), STR_RANKING_NODE);
            HtmlNodeCollection dlist = ranking.SelectNodes("//tr/td[@class='tamer2']");

            if (dlist != null) {
                for (int i = 0; i < dlist.Count; i++) {
                    if (ClearStr(ranking.SelectNodes("//td[@class='tamer2']")[i].InnerText) == tamer.Name) {
                        string size = ranking.SelectNodes("//td[@class='size']")[i + 3].InnerText.Replace("cm", "");
                        string size_cm = size.Substring(0, size.IndexOf(' '));
                        double SizeCm = 0;
                        double.TryParse(size_cm.Replace('.', ','), out SizeCm);
                        digimon.SizeCm = SizeCm;
                        digimon.SizePc = Convert.ToInt32(size.Substring(size.LastIndexOf('(') + 1, size.LastIndexOf('%') - size.LastIndexOf('(') - 1));
                        digimon.SizeRank = Convert.ToInt32(ClearStr(ranking.SelectNodes("//td[@class='ranking']")[i + 3].InnerText));
                        digimon.Name = ClearStr(ranking.SelectNodes("//td[@class='name']")[i + 3].InnerText);
                        return true;
                    }
                }
            }
            return false;
        }
 protected override bool GetStarterInfo(ref Digimon digimon, Tamer tamer)
 {
     if (digimon.Type == null) {
         return false;
     }
     if (LogManager != null) {
         LogManager.InfoFormat("Obtaining starter digimon for tamer \"{0}\"", tamer.Name);
     }
     HtmlNode ranking = tryLoadNode(string.Format(STR_URL_STARTER_RANK, tamer.Name, "srv" + tamer.Guild.Server.Identifier), STR_RANKING_NODE);
     HtmlNodeCollection dlist = ranking.SelectNodes("//tr/td[@class='tamer2']");
     if (dlist != null) {
         for (int i = 0; i < dlist.Count; i++) {
             if (ClearStr(ranking.SelectNodes("//td[@class='tamer2']")[i].InnerText) == tamer.Name) {
                 digimon.Rank = Convert.ToInt32(ClearStr(ranking.SelectNodes("//td[@class='ranking']")[i + 3].InnerText));
                 digimon.Name = ClearStr(ranking.SelectNodes("//td[@class='name']")[i + 3].InnerText);
                 digimon.Level = Convert.ToByte(ClearStr(ranking.SelectNodes("//td[@class='level']")[i + 3].InnerText));
                 return true;
             }
         }
     }
     return false;
 }
        protected override bool GetGuildInfo(ref Guild guild, bool isDetailed)
        {
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining info of {0}", guild.Name);
            }
            List<Tamer> tamerList = new List<Tamer>();
            HtmlNode ranking = tryLoadNode(string.Format(STR_URL_GUILD_PAGE, guild.Identifier, "srv" + guild.Server.Identifier), STR_RANKING_NODE);
            HtmlNodeCollection tlist = ranking.SelectNodes("//tr/td[@class='level']");
            using (IDatabaseContext context = DatabaseManager.CreateContext()) {
                for (int i = 0; i < tlist.Count; i++) {
                    Tamer tamer = new Tamer() {
                        Guild = guild,
                        Name = ClearStr(ranking.SelectNodes("//td[@class='guild']")[i].InnerText),
                        Level = Convert.ToByte(ClearStr(ranking.SelectNodes("//td[@class='level']")[i].InnerText)),
                        Rank = Convert.ToInt32(ClearStr(ranking.SelectNodes("//td[@class='ranking']")[i].InnerText))
                    };
                    OnStatusChanged(DMODownloadStatusCode.GETTING_TAMER, tamer.Name, i, tlist.Count - 1);

                    string tamerType = ranking.SelectNodes("//td[@class='guild']//img")[i].GetAttributeValue("src", null);
                    tamerType = tamerType.Substring(tamerType.LastIndexOf('/') + 1, tamerType.LastIndexOf('.') - tamerType.LastIndexOf('/') - 1);
                    tamer.Type = context.FindTamerTypeByCode(Convert.ToInt32(tamerType));

                    Regex r = new Regex(STR_TAMER_ID_REGEX, RegexOptions.IgnoreCase | RegexOptions.Singleline);
                    Match m = r.Match(ranking.SelectNodes("//td[@class='detail']")[i].InnerHtml);
                    if (m.Success) {
                        tamer.AccountId = Convert.ToInt32(m.Groups[2].ToString());
                        tamer.Digimons = GetDigimons(tamer, isDetailed);

                        Digimon partner = tamer.Digimons.FirstOrDefault(d => d.Type.IsStarter);
                        if (partner != null) {
                            partner.Name = ClearStr(ranking.SelectNodes("//td[@class='partner']")[i].InnerText);
                        }

                        tamerList.Add(tamer);
                        if (LogManager != null) {
                            LogManager.InfoFormat("Found tamer \"{0}\"", tamer.Name);
                        }
                    }
                }
            }
            if (tamerList.Count == 0) {
                return false;
            }
            guild.Tamers = tamerList;
            return true;
        }
        protected override List<Digimon> GetDigimons(Tamer tamer, bool isDetailed)
        {
            if (LogManager != null) {
                LogManager.InfoFormat("Obtaining digimons for tamer \"{0}\"", tamer.Name);
            }
            List<Digimon> digimonList = new List<Digimon>();

            using (IDatabaseContext context = DatabaseManager.CreateContext()) {
                HtmlDocument doc;
                //getting starter
                HtmlNode tamerInfo = tryLoadNode(string.Format(STR_URL_TAMER_POPPAGE, tamer.AccountId, "srv" + tamer.Guild.Server.Identifier), "//div[@class='tamer-area']", out doc);
                Digimon partner = new Digimon() {
                    Tamer = tamer,
                    SizePc = 100,
                    Name = ClearStr(tamerInfo.SelectNodes("//ul/li[@class='partner']/span")[0].InnerText)
                };
                partner.Type = context.FindDigimonTypeBySearchGDMO(context.PrepareDigimonSearch(partner.Name));
                partner.SizeCm = partner.Type.SizeCm;
                digimonList.Add(partner);
                if (!GetStarterInfo(ref partner, tamer)) {
                    if (LogManager != null) {
                        LogManager.ErrorFormat("Unable to obtain info about starter digimon \"{0}\" for tamer \"{1}\"", partner.Name, tamer.Name);
                    }
                }

                HtmlNode mercenaryList = doc.DocumentNode.SelectNodes("//div[@id='rankingscroll']")[0];
                HtmlNodeCollection dlist = mercenaryList.SelectNodes("//li/em[@class='partner']");

                if (dlist != null) {
                    for (int i = 0; i < dlist.Count; i++) {
                        Digimon digimonInfo = new Digimon() {
                            Tamer = tamer,
                            Name = ClearStr(mercenaryList.SelectNodes("//em[@class='partner']")[i].InnerText),
                            Level = Convert.ToByte(ClearStr(mercenaryList.SelectNodes("//span[@class='level']")[i].InnerText)),
                            Rank = Convert.ToInt32(ClearStr(mercenaryList.SelectNodes("//span[@class='ranking']")[i].InnerText))
                        };
                        digimonInfo.Type = context.FindDigimonTypeBySearchGDMO(context.PrepareDigimonSearch(digimonInfo.Name));
                        if (digimonInfo.Type == null) {
                            continue;
                        }
                        digimonInfo.SizeCm = digimonInfo.Type.SizeCm;

                        if (digimonList.Count(d => d.Type.Equals(digimonInfo.Type)) == 0) {
                            if (isDetailed) {
                                if (!GetMercenaryInfo(ref digimonInfo, tamer)) {
                                    if (LogManager != null) {
                                        LogManager.ErrorFormat("Unable to obtain detailed data of digimon \"{0}\" for tamer \"{1}\"", digimonInfo.Name, tamer.Name);
                                    }
                                }
                            }
                            digimonList.Add(digimonInfo);
                            if (LogManager != null) {
                                LogManager.Info(String.Format("Found digimon \"{0}\"", digimonInfo.Name));
                            }
                        }
                    }
                }
            }
            return digimonList;
        }
 /// <summary>
 /// Returns tamer's starter detailed information
 /// </summary>
 /// <param name="digimon">Starter reference</param>
 /// <param name="tamer">Tamer</param>
 /// <returns><b>True</b> on success</returns>
 protected abstract bool GetStarterInfo(ref Digimon digimon, Tamer tamer);
 /// <summary>
 /// Returns tamer's mercenary detailed information
 /// </summary>
 /// <param name="digimon">Mercenary reference</param>
 /// <param name="tamer">Tamer</param>
 /// <returns><b>True</b> on success</returns>
 protected abstract bool GetMercenaryInfo(ref Digimon digimon, Tamer tamer);
 /// <summary>
 /// Returns digimon list for tamer
 /// </summary>
 /// <param name="tamer">Tamer to update</param>
 /// <param name="isDetailed">Shoul it be detailed data (like digimon size, real name, etc)</param>
 /// <returns>Digimon list</returns>
 protected abstract List<Digimon> GetDigimons(Tamer tamer, bool isDetailed);