public void Delete(int id)
        {
            using (var session = JMMService.SessionFactory.OpenSession())
            {
                // populate the database
                using (var transaction = session.BeginTransaction())
                {
                    CustomTag cr = GetByID(id);
                    if (cr != null)
                    {
                        // first delete any cross ref records 
                        CrossRef_CustomTagRepository repXrefs = new CrossRef_CustomTagRepository();
                        foreach (CrossRef_CustomTag xref in repXrefs.GetByCustomTagID(session, id))
                            repXrefs.Delete(xref.CrossRef_CustomTagID);

                        session.Delete(cr);
                        transaction.Commit();
                    }
                }
            }
        }
        public void Delete(int id)
        {
            using (var session = JMMService.SessionFactory.OpenSession())
            {
                // populate the database
                using (var transaction = session.BeginTransaction())
                {
                    CustomTag cr = GetByID(id);
                    if (cr != null)
                    {
                        // first delete any cross ref records
                        CrossRef_CustomTagRepository repXrefs = new CrossRef_CustomTagRepository();
                        foreach (CrossRef_CustomTag xref in repXrefs.GetByCustomTagID(session, id))
                        {
                            repXrefs.Delete(xref.CrossRef_CustomTagID);
                        }

                        session.Delete(cr);
                        transaction.Commit();
                    }
                }
            }
        }
Exemple #3
0
        public string DeleteCustomTagCrossRefByID(int xrefID)
        {
            try
            {
                CrossRef_CustomTagRepository repCustomTagsXrefs = new CrossRef_CustomTagRepository();

                CrossRef_CustomTag pl = repCustomTagsXrefs.GetByID(xrefID);
                if (pl == null)
                    return "Custom Tag not found";

                repCustomTagsXrefs.Delete(xrefID);

                return "";
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return ex.Message;
            }
        }
Exemple #4
0
        public Contract_CrossRef_CustomTag_SaveResponse SaveCustomTagCrossRef(Contract_CrossRef_CustomTag contract)
        {
            Contract_CrossRef_CustomTag_SaveResponse contractRet = new Contract_CrossRef_CustomTag_SaveResponse();
            contractRet.ErrorMessage = "";

            try
            {
                CrossRef_CustomTagRepository repCustomTagsXRefs = new CrossRef_CustomTagRepository();

                // this is an update
                CrossRef_CustomTag xref = null;
                if (contract.CrossRef_CustomTagID.HasValue)
                {
                    contractRet.ErrorMessage = "Updates are not allowed";
                    return contractRet;
                }
                else
                    xref = new CrossRef_CustomTag();

                //TODO: Custom Tags - check if the CustomTagID is valid
                //TODO: Custom Tags - check if the CrossRefID is valid

                xref.CrossRefID = contract.CrossRefID;
                xref.CrossRefType = contract.CrossRefType;
                xref.CustomTagID = contract.CustomTagID;

                repCustomTagsXRefs.Save(xref);

                contractRet.CrossRef_CustomTag = xref.ToContract();

                StatsCache.Instance.UpdateAnimeContract(contract.CrossRefID);
                StatsCache.Instance.UpdateUsingAnime(contract.CrossRefID);
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                contractRet.ErrorMessage = ex.Message;
                return contractRet;
            }

            return contractRet;
        }
Exemple #5
0
        public string DeleteCustomTagCrossRef(int customTagID, int crossRefType, int crossRefID)
        {
            try
            {
                CrossRef_CustomTagRepository repCustomTagsXrefs = new CrossRef_CustomTagRepository();

                List<CrossRef_CustomTag> xrefs = repCustomTagsXrefs.GetByUniqueID(customTagID, crossRefType, crossRefID);

                if (xrefs == null || xrefs.Count == 0)
                    return "Custom Tag not found";

                repCustomTagsXrefs.Delete(xrefs[0].CrossRef_CustomTagID);
                StatsCache.Instance.UpdateAnimeContract(crossRefID);
                StatsCache.Instance.UpdateUsingAnime(crossRefID);

                return "";
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return ex.Message;
            }
        }
Exemple #6
0
        public string DeleteCustomTag(int customTagID)
        {
            try
            {
                CustomTagRepository repCustomTags = new CustomTagRepository();

                CustomTag pl = repCustomTags.GetByID(customTagID);
                if (pl == null)
                    return "Custom Tag not found";

                // first get a list of all the anime that referenced this tag
                CrossRef_CustomTagRepository repCustomTagsXRefs = new CrossRef_CustomTagRepository();
                List<CrossRef_CustomTag> xrefs = repCustomTagsXRefs.GetByCustomTagID(customTagID);

                repCustomTags.Delete(customTagID);

                // update cached data for any anime that were affected
                foreach (CrossRef_CustomTag xref in xrefs)
                {
                    StatsCache.Instance.UpdateAnimeContract(xref.CrossRefID);
                    StatsCache.Instance.UpdateUsingAnime(xref.CrossRefID);
                }

                return "";
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
                return ex.Message;
            }
        }
Exemple #7
0
        public List<Contract_AniDB_AnimeDetailed> GetAllAnimeDetailed()
        {
            List<Contract_AniDB_AnimeDetailed> contracts = new List<Contract_AniDB_AnimeDetailed>();
            int countElements = 0;
            try
            {
                DateTime start = DateTime.Now;

                AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();

                // build a dictionary of titles
                AniDB_Anime_TitleRepository repTitles = new AniDB_Anime_TitleRepository();

                List<AniDB_Anime_Title> allTitles = repTitles.GetAll();
                Dictionary<int, List<AniDB_Anime_Title>> allTitlesDict = new Dictionary<int, List<AniDB_Anime_Title>>();
                foreach (AniDB_Anime_Title title in allTitles)
                {
                    if (!allTitlesDict.ContainsKey(title.AnimeID))
                        allTitlesDict[title.AnimeID] = new List<AniDB_Anime_Title>();

                    allTitlesDict[title.AnimeID].Add(title);
                }

                // build a dictionary of tags
                AniDB_TagRepository repTags = new AniDB_TagRepository();
                AniDB_Anime_TagRepository repAnimeTag = new AniDB_Anime_TagRepository();

                List<AniDB_Tag> allTags = repTags.GetAll();
                Dictionary<int, AniDB_Tag> allTagsDict = new Dictionary<int, AniDB_Tag>();
                foreach (AniDB_Tag tag in allTags)
                    allTagsDict[tag.TagID] = tag;

                List<AniDB_Anime_Tag> allAnimeTags = repAnimeTag.GetAll();
                Dictionary<int, List<AniDB_Anime_Tag>> allAnimeTagsDict = new Dictionary<int, List<AniDB_Anime_Tag>>(); //
                foreach (AniDB_Anime_Tag aniTag in allAnimeTags)
                {
                    if (!allAnimeTagsDict.ContainsKey(aniTag.AnimeID))
                        allAnimeTagsDict[aniTag.AnimeID] = new List<AniDB_Anime_Tag>();

                    allAnimeTagsDict[aniTag.AnimeID].Add(aniTag);
                }

                // build a dictionary of custom tags
                CustomTagRepository repCustomTags = new CustomTagRepository();
                CrossRef_CustomTagRepository repXRefCustomTags = new CrossRef_CustomTagRepository();

                List<CustomTag> allCustomTags = repCustomTags.GetAll();
                Dictionary<int, CustomTag> allCustomTagsDict = new Dictionary<int, CustomTag>();
                foreach (CustomTag tag in allCustomTags)
                    allCustomTagsDict[tag.CustomTagID] = tag;

                List<CrossRef_CustomTag> allCustomTagsXRefs = repXRefCustomTags.GetAll();
                Dictionary<int, List<CrossRef_CustomTag>> allCustomTagsXRefDict = new Dictionary<int, List<CrossRef_CustomTag>>(); //
                foreach (CrossRef_CustomTag aniTag in allCustomTagsXRefs)
                {
                    if (!allCustomTagsXRefDict.ContainsKey(aniTag.CrossRefID))
                        allCustomTagsXRefDict[aniTag.CrossRefID] = new List<CrossRef_CustomTag>();

                    allCustomTagsXRefDict[aniTag.CrossRefID].Add(aniTag);
                }

                // build a dictionary of languages
                AdhocRepository rep = new AdhocRepository();
                Dictionary<int, LanguageStat> dictAudioStats = rep.GetAudioLanguageStatsForAnime();
                Dictionary<int, LanguageStat> dictSubtitleStats = rep.GetSubtitleLanguageStatsForAnime();

                Dictionary<int, string> dictAnimeVideoQualStats = rep.GetAllVideoQualityByAnime();
                Dictionary<int, AnimeVideoQualityStat> dictAnimeEpisodeVideoQualStats = rep.GetEpisodeVideoQualityStatsByAnime();

                List<AniDB_Anime> animes = repAnime.GetAll();

                // user votes
                AniDB_VoteRepository repVotes = new AniDB_VoteRepository();
                List<AniDB_Vote> allVotes = repVotes.GetAll();

                int i = 0;

                foreach (AniDB_Anime anime in animes)
                {
                    i++;
                    //if (i >= 10) continue;

                    countElements++;

                    Contract_AniDB_AnimeDetailed contract = new Contract_AniDB_AnimeDetailed();

                    contract.AnimeTitles = new List<Contract_AnimeTitle>();
                    contract.Tags = new List<Contract_AnimeTag>();
                    contract.CustomTags = new List<Contract_CustomTag>();
                    contract.UserVote = null;

                    contract.AniDBAnime = anime.ToContract();

                    if (dictAnimeVideoQualStats.ContainsKey(anime.AnimeID))
                        contract.Stat_AllVideoQuality = dictAnimeVideoQualStats[anime.AnimeID];
                    else contract.Stat_AllVideoQuality = "";

                    contract.Stat_AllVideoQuality_Episodes = "";

                    // All Video Quality Episodes
                    // Try to determine if this anime has all the episodes available at a certain video quality
                    // e.g.  the series has all episodes in blu-ray
                    if (dictAnimeEpisodeVideoQualStats.ContainsKey(anime.AnimeID))
                    {
                        AnimeVideoQualityStat stat = dictAnimeEpisodeVideoQualStats[anime.AnimeID];
                        foreach (KeyValuePair<string, int> kvp in stat.VideoQualityEpisodeCount)
                        {
                            if (kvp.Value >= anime.EpisodeCountNormal)
                            {
                                if (contract.Stat_AllVideoQuality_Episodes.Length > 0) contract.Stat_AllVideoQuality_Episodes += ",";
                                contract.Stat_AllVideoQuality_Episodes += kvp.Key;
                            }
                        }
                    }

                    List<string> audioLanguageList = new List<string>();
                    List<string> subtitleLanguageList = new List<string>();

                    // get audio languages
                    if (dictAudioStats.ContainsKey(anime.AnimeID))
                    {
                        foreach (string lanName in dictAudioStats[anime.AnimeID].LanguageNames)
                        {
                            if (!audioLanguageList.Contains(lanName)) audioLanguageList.Add(lanName);
                        }
                    }

                    // get subtitle languages
                    if (dictSubtitleStats.ContainsKey(anime.AnimeID))
                    {
                        foreach (string lanName in dictSubtitleStats[anime.AnimeID].LanguageNames)
                        {
                            if (!subtitleLanguageList.Contains(lanName)) subtitleLanguageList.Add(lanName);
                        }
                    }

                    contract.Stat_AudioLanguages = "";
                    foreach (string audioLan in audioLanguageList)
                    {
                        if (contract.Stat_AudioLanguages.Length > 0) contract.Stat_AudioLanguages += ",";
                        contract.Stat_AudioLanguages += audioLan;
                    }

                    contract.Stat_SubtitleLanguages = "";
                    foreach (string subLan in subtitleLanguageList)
                    {
                        if (contract.Stat_SubtitleLanguages.Length > 0) contract.Stat_SubtitleLanguages += ",";
                        contract.Stat_SubtitleLanguages += subLan;
                    }

                    if (allTitlesDict.ContainsKey(anime.AnimeID))
                    {
                        foreach (AniDB_Anime_Title title in allTitlesDict[anime.AnimeID])
                        {
                            Contract_AnimeTitle ctitle = new Contract_AnimeTitle();
                            ctitle.AnimeID = title.AnimeID;
                            ctitle.Language = title.Language;
                            ctitle.Title = title.Title;
                            ctitle.TitleType = title.TitleType;
                            contract.AnimeTitles.Add(ctitle);
                            countElements++;
                        }
                    }

                    if (allAnimeTagsDict.ContainsKey(anime.AnimeID))
                    {
                        List<AniDB_Anime_Tag> aniTags = allAnimeTagsDict[anime.AnimeID];
                        foreach (AniDB_Anime_Tag aniTag in aniTags)
                        {
                            if (allTagsDict.ContainsKey(aniTag.TagID))
                            {
                                AniDB_Tag tag = allTagsDict[aniTag.TagID];

                                Contract_AnimeTag ctag = new Contract_AnimeTag();
                                ctag.Weight = aniTag.Weight;
                                ctag.GlobalSpoiler = tag.GlobalSpoiler;
                                ctag.LocalSpoiler = tag.LocalSpoiler;
                                //ctag.Spoiler = tag.Spoiler;
                                //ctag.TagCount = tag.TagCount;
                                ctag.TagDescription = tag.TagDescription;
                                ctag.TagID = tag.TagID;
                                ctag.TagName = tag.TagName;
                                contract.Tags.Add(ctag);
                                countElements++;
                            }
                        }
                    }

                    //TODO - Custom Tags: add custom tags

                    if (allCustomTagsXRefDict.ContainsKey(anime.AnimeID))
                    {
                        List<CrossRef_CustomTag> aniTags = allCustomTagsXRefDict[anime.AnimeID];
                        foreach (CrossRef_CustomTag aniTag in aniTags)
                        {
                            if (allCustomTagsDict.ContainsKey(aniTag.CustomTagID))
                            {
                                contract.CustomTags.Add(allCustomTagsDict[aniTag.CustomTagID].ToContract());
                                countElements++;
                            }
                        }
                    }

                    // get user vote
                    foreach (AniDB_Vote vote in allVotes)
                    {
                        if (vote.EntityID == anime.AnimeID && (vote.VoteType == (int)AniDBVoteType.Anime || vote.VoteType == (int)AniDBVoteType.AnimeTemp))
                        {
                            contract.UserVote = vote.ToContract();
                            break;
                        }
                    }

                    contracts.Add(contract);

                }

                TimeSpan ts = DateTime.Now - start;
                logger.Info("GetAllAnimeDetailed in {0} ms {1}", ts.TotalMilliseconds, countElements);
            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }
            return contracts;
        }
Exemple #8
0
        public void InitStats()
        {
            try
            {

                DateTime start = DateTime.Now;

                ClearAllData();

                #region Get the data
                AnimeGroupRepository repGroups = new AnimeGroupRepository();
                AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
                AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
                AniDB_TagRepository repTags = new AniDB_TagRepository();
                AniDB_Anime_TagRepository repAnimeTag = new AniDB_Anime_TagRepository();
                AniDB_Anime_TitleRepository repTitles = new AniDB_Anime_TitleRepository();

                List<AnimeGroup> allGrps = repGroups.GetAll();

                Dictionary<int, AnimeGroup> allGroupsDict = new Dictionary<int, AnimeGroup>();
                foreach (AnimeGroup agrp in allGrps)
                    allGroupsDict[agrp.AnimeGroupID] = agrp;
                TimeSpan ts = DateTime.Now - start;
                logger.Info("Get All GROUPS (Database) in {0} ms", ts.TotalMilliseconds);

                // anime
                start = DateTime.Now;
                List<AniDB_Anime> allAnime = repAnime.GetAll();
                Dictionary<int, AniDB_Anime> allAnimeDict = new Dictionary<int, AniDB_Anime>();
                foreach (AniDB_Anime anime in allAnime)
                    allAnimeDict[anime.AnimeID] = anime;

                ts = DateTime.Now - start;
                logger.Info("Get All ANIME (Database) in {0} ms", ts.TotalMilliseconds);

                // tags
                start = DateTime.Now;
                List<AniDB_Tag> allTags = repTags.GetAll();
                Dictionary<int, AniDB_Tag> allTagsDict = new Dictionary<int, AniDB_Tag>();
                foreach (AniDB_Tag tag in allTags)
                    allTagsDict[tag.TagID] = tag;

                List<AniDB_Anime_Tag> allAnimeTags = repAnimeTag.GetAll();
                Dictionary<int, List<int>> allAnimeTagsDict = new Dictionary<int, List<int>>(); // animeid / list of tag id's
                foreach (AniDB_Anime_Tag aniTag in allAnimeTags)
                {
                    if (!allAnimeTagsDict.ContainsKey(aniTag.AnimeID))
                        allAnimeTagsDict[aniTag.AnimeID] = new List<int>();

                    allAnimeTagsDict[aniTag.AnimeID].Add(aniTag.TagID);
                }
                ts = DateTime.Now - start;
                logger.Info("Get All TAGS (Database) in {0} ms", ts.TotalMilliseconds);

                // custom tags
                CustomTagRepository repCustomTags = new CustomTagRepository();
                CrossRef_CustomTagRepository repXRefCustomTags = new CrossRef_CustomTagRepository();

                List<CustomTag> allCustomTags = repCustomTags.GetAll();
                Dictionary<int, CustomTag> allCustomTagsDict = new Dictionary<int, CustomTag>();
                foreach (CustomTag tag in allCustomTags)
                    allCustomTagsDict[tag.CustomTagID] = tag;

                List<CrossRef_CustomTag> allCustomTagsXRefs = repXRefCustomTags.GetAll();
                Dictionary<int, List<CrossRef_CustomTag>> allCustomTagsXRefDict = new Dictionary<int, List<CrossRef_CustomTag>>(); //
                foreach (CrossRef_CustomTag aniTag in allCustomTagsXRefs)
                {
                    if (!allCustomTagsXRefDict.ContainsKey(aniTag.CrossRefID))
                        allCustomTagsXRefDict[aniTag.CrossRefID] = new List<CrossRef_CustomTag>();

                    allCustomTagsXRefDict[aniTag.CrossRefID].Add(aniTag);
                }

                // titles
                start = DateTime.Now;
                List<AniDB_Anime_Title> allTitles = repTitles.GetAll();
                Dictionary<int, List<AniDB_Anime_Title>> allTitlesDict = new Dictionary<int, List<AniDB_Anime_Title>>(); // animeid / list of titles
                foreach (AniDB_Anime_Title aniTitle in allTitles)
                {
                    if (!allTitlesDict.ContainsKey(aniTitle.AnimeID))
                        allTitlesDict[aniTitle.AnimeID] = new List<AniDB_Anime_Title>();

                    allTitlesDict[aniTitle.AnimeID].Add(aniTitle);
                }
                ts = DateTime.Now - start;
                logger.Info("Get All TITLES (Database) in {0} ms", ts.TotalMilliseconds);

                // user votes
                start = DateTime.Now;
                AniDB_VoteRepository repVotes = new AniDB_VoteRepository();
                List<AniDB_Vote> allVotes = repVotes.GetAll();
                ts = DateTime.Now - start;
                logger.Info("Get All VOTES (Database) in {0} ms", ts.TotalMilliseconds);

                // video quality
                start = DateTime.Now;
                AdhocRepository rep = new AdhocRepository();
                Dictionary<int, string> allVidQuality = rep.GetAllVideoQualityByGroup();

                ts = DateTime.Now - start;
                logger.Info("Get VIDEO QUALITY STATS (Database) in {0} ms", ts.TotalMilliseconds);

                // video quality episode stats
                start = DateTime.Now;
                Dictionary<int, AnimeVideoQualityStat> dictStats = rep.GetEpisodeVideoQualityStatsByAnime();
                ts = DateTime.Now - start;
                logger.Info("Get VIDEO QUALITY EPISODE STATS (Database) in {0} ms", ts.TotalMilliseconds);

                // audio and subtitle language stats
                start = DateTime.Now;
                Dictionary<int, LanguageStat> dictAudioStats = rep.GetAudioLanguageStatsForAnime();
                Dictionary<int, LanguageStat> dictSubtitleStats = rep.GetSubtitleLanguageStatsForAnime();
                ts = DateTime.Now - start;
                logger.Info("Get LANGUAGE STATS (Database) in {0} ms", ts.TotalMilliseconds);

                start = DateTime.Now;
                List<AnimeSeries> allSeries = repSeries.GetAll();
                ts = DateTime.Now - start;
                logger.Info("Get All Series (Database) in {0} ms", ts.TotalMilliseconds);

                // TvDB
                start = DateTime.Now;
                CrossRef_AniDB_TvDBV2Repository repCrossRef = new CrossRef_AniDB_TvDBV2Repository();
                List<CrossRef_AniDB_TvDBV2> allCrossRefs = repCrossRef.GetAll();
                List<int> animeWithTvDBCrossRef = new List<int>();
                foreach (CrossRef_AniDB_TvDBV2 xref in allCrossRefs)
                {
                    if (!animeWithTvDBCrossRef.Contains(xref.AnimeID)) animeWithTvDBCrossRef.Add(xref.AnimeID);
                }
                ts = DateTime.Now - start;
                logger.Info("Get All AniDB->TvDB Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);

                // MovieDB
                start = DateTime.Now;
                CrossRef_AniDB_OtherRepository repOtherCrossRef = new CrossRef_AniDB_OtherRepository();
                List<CrossRef_AniDB_Other> allOtherCrossRefs = repOtherCrossRef.GetAll();
                List<int> animeWithMovieCrossRef = new List<int>();
                foreach (CrossRef_AniDB_Other xref in allOtherCrossRefs)
                {
                    if (!animeWithMovieCrossRef.Contains(xref.AnimeID) && xref.CrossRefType == (int)CrossRefType.MovieDB)
                        animeWithMovieCrossRef.Add(xref.AnimeID);
                }
                ts = DateTime.Now - start;
                logger.Info("Get All AniDB->MovieDB Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);

                // MAL
                start = DateTime.Now;
                CrossRef_AniDB_MALRepository repMALCrossRef = new CrossRef_AniDB_MALRepository();
                List<CrossRef_AniDB_MAL> allMALCrossRefs = repMALCrossRef.GetAll();
                List<int> animeWithMALCrossRef = new List<int>();
                foreach (CrossRef_AniDB_MAL xref in allMALCrossRefs)
                {
                    if (!animeWithMALCrossRef.Contains(xref.AnimeID))
                        animeWithMALCrossRef.Add(xref.AnimeID);
                }
                ts = DateTime.Now - start;
                logger.Info("Get All AniDB->MAL Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);

                #endregion

                start = DateTime.Now;
                var session = JMMService.SessionFactory.OpenSession();
                foreach (AnimeGroup ag in allGrps)
                {
                    // get all the series for this group
                    List<AnimeSeries> seriesForGroup = new List<AnimeSeries>();
                    GetAnimeSeriesRecursive(ag, ref seriesForGroup, allSeries, allGroupsDict);
                    /*
                    if (ag.AnimeGroupID == 915)
                    {
                        Console.Write("");
                    }

                    */
                    DateTime? Stat_AirDate_Min = null;
                    DateTime? Stat_AirDate_Max = null;
                    DateTime? Stat_EndDate = new DateTime(1980, 1, 1);
                    DateTime? Stat_SeriesCreatedDate = null;
                    bool isComplete = false;
                    bool hasFinishedAiring = false;
                    bool isCurrentlyAiring = false;

                    List<int> tagIDList = new List<int>();
                    List<int> customTagIDList = new List<int>();
                    List<string> audioLanguageList = new List<string>();
                    List<string> subtitleLanguageList = new List<string>();
                    string Stat_AllTitles = "";
                    string Stat_AllTags = "";
                    string Stat_AllCustomTags = "";
                    string Stat_AllVideoQualityEpisodes = "";

                    decimal totalVotesPerm = 0, totalVotesTemp = 0, totalVotes = 0;
                    int countVotesPerm = 0, countVotesTemp = 0, countVotes = 0;

                    bool hasTvDB = true;
                    bool hasMAL = true;
                    bool hasMovieDB = true;
                    bool hasMovieDBOrTvDB = true;

                    int seriesCount = 0;
                    int epCount = 0;

                    foreach (AnimeSeries series in seriesForGroup)
                    {
                        seriesCount++;
                        if (allAnimeDict.ContainsKey(series.AniDB_ID))
                        {
                            AniDB_Anime thisAnime = allAnimeDict[series.AniDB_ID];

                            epCount = epCount + thisAnime.EpisodeCountNormal;

                            // All Video Quality Episodes
                            // Try to determine if this anime has all the episodes available at a certain video quality
                            // e.g.  the series has all episodes in blu-ray
                            if (dictStats.ContainsKey(series.AniDB_ID))
                            {
                                if (series.AniDB_ID == 7656)
                                {
                                    Debug.Print("");
                                }

                                AnimeVideoQualityStat stat = dictStats[series.AniDB_ID];
                                foreach (KeyValuePair<string, int> kvp in stat.VideoQualityEpisodeCount)
                                {
                                    if (kvp.Value >= thisAnime.EpisodeCountNormal)
                                    {
                                        if (Stat_AllVideoQualityEpisodes.Length > 0) Stat_AllVideoQualityEpisodes += ",";
                                        Stat_AllVideoQualityEpisodes += kvp.Key;
                                    }
                                }
                            }

                            // Calculate Air Date
                            DateTime? thisDate = thisAnime.AirDate;
                            if (thisDate.HasValue)
                            {
                                if (Stat_AirDate_Min.HasValue)
                                {
                                    if (thisDate.Value < Stat_AirDate_Min.Value) Stat_AirDate_Min = thisDate;
                                }
                                else
                                    Stat_AirDate_Min = thisDate;

                                if (Stat_AirDate_Max.HasValue)
                                {
                                    if (thisDate.Value > Stat_AirDate_Max.Value) Stat_AirDate_Max = thisDate;
                                }
                                else
                                    Stat_AirDate_Max = thisDate;
                            }

                            // calculate end date
                            // if the end date is NULL it actually means it is ongoing, so this is the max possible value
                            thisDate = thisAnime.EndDate;
                            if (thisDate.HasValue && Stat_EndDate.HasValue)
                            {
                                if (thisDate.Value > Stat_EndDate.Value) Stat_EndDate = thisDate;
                            }
                            else
                                Stat_EndDate = null;

                            // Calculate Series Created Date
                            thisDate = series.DateTimeCreated;
                            if (thisDate.HasValue)
                            {
                                if (Stat_SeriesCreatedDate.HasValue)
                                {
                                    if (thisDate.Value < Stat_SeriesCreatedDate.Value) Stat_SeriesCreatedDate = thisDate;
                                }
                                else
                                    Stat_SeriesCreatedDate = thisDate;
                            }
                            /*
                            if (series.AniDB_ID == 2369)
                                Debug.Write("Test");
                            */
                            // Note - only one series has to be finished airing to qualify
                            if (thisAnime.EndDate.HasValue && thisAnime.EndDate.Value < DateTime.Now)
                                hasFinishedAiring = true;

                            // Note - only one series has to be currently airing to qualify
                            if (!thisAnime.EndDate.HasValue || thisAnime.EndDate.Value > DateTime.Now)
                                isCurrentlyAiring = true;

                            // We evaluate IsComplete as true if
                            // 1. series has finished airing
                            // 2. user has all episodes locally
                            // Note - only one series has to be complete for the group to be considered complete
                            if (thisAnime.EndDate.HasValue)
                            {
                                if (thisAnime.EndDate.Value < DateTime.Now && series.MissingEpisodeCount == 0 && series.MissingEpisodeCountGroups == 0)
                                {
                                    isComplete = true;
                                }
                            }

                            // get categories
                            if (allAnimeTagsDict.ContainsKey(series.AniDB_ID))
                            {
                                foreach (int catID in allAnimeTagsDict[series.AniDB_ID])
                                {
                                    if (!tagIDList.Contains(catID)) tagIDList.Add(catID);
                                }
                            }

                            // get custom tags
                            if (allCustomTagsXRefDict.ContainsKey(series.AniDB_ID))
                            {
                                foreach (CrossRef_CustomTag xtag in allCustomTagsXRefDict[series.AniDB_ID])
                                {
                                    if (!customTagIDList.Contains(xtag.CustomTagID)) customTagIDList.Add(xtag.CustomTagID);
                                }
                            }

                            // get audio languages
                            if (dictAudioStats.ContainsKey(series.AniDB_ID))
                            {
                                foreach (string lanName in dictAudioStats[series.AniDB_ID].LanguageNames)
                                {
                                    if (!audioLanguageList.Contains(lanName)) audioLanguageList.Add(lanName);
                                }
                            }

                            // get subtitle languages
                            if (dictSubtitleStats.ContainsKey(series.AniDB_ID))
                            {
                                foreach (string lanName in dictSubtitleStats[series.AniDB_ID].LanguageNames)
                                {
                                    if (!subtitleLanguageList.Contains(lanName)) subtitleLanguageList.Add(lanName);
                                }
                            }

                            // get titles
                            if (allTitlesDict.ContainsKey(series.AniDB_ID))
                            {
                                foreach (AniDB_Anime_Title title in allTitlesDict[series.AniDB_ID])
                                {
                                    if (Stat_AllTitles.Length > 0) Stat_AllTitles += ",";
                                    Stat_AllTitles += title.Title;
                                }
                            }

                            // get votes
                            foreach (AniDB_Vote vote in allVotes)
                            {
                                if (vote.EntityID == series.AniDB_ID && (vote.VoteType == (int)AniDBVoteType.Anime || vote.VoteType == (int)AniDBVoteType.AnimeTemp))
                                {
                                    countVotes++;
                                    totalVotes += (decimal)vote.VoteValue;

                                    if (vote.VoteType == (int)AniDBVoteType.Anime)
                                    {
                                        countVotesPerm++;
                                        totalVotesPerm += (decimal)vote.VoteValue;
                                    }
                                    if (vote.VoteType == (int)AniDBVoteType.AnimeTemp)
                                    {
                                        countVotesTemp++;
                                        totalVotesTemp += (decimal)vote.VoteValue;
                                    }

                                    break;
                                }
                            }
                        }

                        // for the group, if any of the series don't have a tvdb link
                        // we will consider the group as not having a tvdb link
                        if (!animeWithTvDBCrossRef.Contains(series.AniDB_ID)) hasTvDB = false;
                        if (!animeWithMovieCrossRef.Contains(series.AniDB_ID)) hasMovieDB = false;
                        if (!animeWithMALCrossRef.Contains(series.AniDB_ID)) hasMAL = false;

                        if (!animeWithTvDBCrossRef.Contains(series.AniDB_ID) && !animeWithMovieCrossRef.Contains(series.AniDB_ID)) hasMovieDBOrTvDB = false;
                    }

                    if (allVidQuality.ContainsKey(ag.AnimeGroupID))
                        StatGroupVideoQuality[ag.AnimeGroupID] = allVidQuality[ag.AnimeGroupID];
                    else
                        StatGroupVideoQuality[ag.AnimeGroupID] = "";

                    StatGroupVideoQualityEpisodes[ag.AnimeGroupID] = Stat_AllVideoQualityEpisodes;

                    StatGroupIsComplete[ag.AnimeGroupID] = isComplete;
                    StatGroupIsFinishedAiring[ag.AnimeGroupID] = hasFinishedAiring;
                    StatGroupIsCurrentlyAiring[ag.AnimeGroupID] = isCurrentlyAiring;
                    StatGroupSeriesCount[ag.AnimeGroupID] = seriesCount;
                    StatGroupEpisodeCount[ag.AnimeGroupID] = epCount;

                    StatGroupTitles[ag.AnimeGroupID] = Stat_AllTitles;
                    StatGroupAirDate_Max[ag.AnimeGroupID] = Stat_AirDate_Max;
                    StatGroupAirDate_Min[ag.AnimeGroupID] = Stat_AirDate_Min;
                    StatGroupEndDate[ag.AnimeGroupID] = Stat_EndDate;
                    StatGroupSeriesCreatedDate[ag.AnimeGroupID] = Stat_SeriesCreatedDate;
                    StatGroupHasTvDB[ag.AnimeGroupID] = hasTvDB;
                    StatGroupHasMAL[ag.AnimeGroupID] = hasMAL;
                    StatGroupHasMovieDB[ag.AnimeGroupID] = hasMovieDB;
                    StatGroupHasMovieDBOrTvDB[ag.AnimeGroupID] = hasMovieDBOrTvDB;

                    decimal? Stat_UserVoteOverall = null;
                    if (countVotes > 0)
                        Stat_UserVoteOverall = totalVotes / (decimal)countVotes / (decimal)100;
                    StatGroupUserVoteOverall[ag.AnimeGroupID] = Stat_UserVoteOverall;

                    decimal? Stat_UserVotePermanent = null;
                    if (countVotesPerm > 0)
                        Stat_UserVotePermanent = totalVotesPerm / (decimal)countVotesPerm / (decimal)100;
                    StatGroupUserVotePermanent[ag.AnimeGroupID] = Stat_UserVotePermanent;

                    decimal? Stat_UserVoteTemporary = null;
                    if (countVotesTemp > 0)
                        Stat_UserVoteTemporary = totalVotesTemp / (decimal)countVotesTemp / (decimal)100;
                    StatGroupUserVoteTemporary[ag.AnimeGroupID] = Stat_UserVoteTemporary;

                    StatGroupAniDBRating[ag.AnimeGroupID] = ag.AniDBRating;

                    // tags
                    Stat_AllTags = "";

                    foreach (int tagID in tagIDList)
                    {
                        if (!allTagsDict.ContainsKey(tagID)) continue;

                        string catName = allTagsDict[tagID].TagName;
                        if (Stat_AllTags.Length > 0)
                            Stat_AllTags += "|";

                        Stat_AllTags += catName;
                    }
                    this.StatGroupTags[ag.AnimeGroupID] = Stat_AllTags;

                    // custom tags
                    Stat_AllCustomTags = "";

                    foreach (int tagID in customTagIDList)
                    {

                        if (!allCustomTagsDict.ContainsKey(tagID)) continue;

                        string tagName = allCustomTagsDict[tagID].TagName;
                        if (Stat_AllCustomTags.Length > 0)
                            Stat_AllCustomTags += "|";

                        Stat_AllCustomTags += tagName;
                    }
                    this.StatGroupCustomTags[ag.AnimeGroupID] = Stat_AllCustomTags;

                    string Stat_AudioLanguages = "";
                    foreach (string audioLan in audioLanguageList)
                    {
                        if (Stat_AudioLanguages.Length > 0) Stat_AudioLanguages += ",";
                        Stat_AudioLanguages += audioLan;
                    }
                    this.StatGroupAudioLanguages[ag.AnimeGroupID] = Stat_AudioLanguages;

                    string Stat_SubtitleLanguages = "";
                    foreach (string subLan in subtitleLanguageList)
                    {
                        if (Stat_SubtitleLanguages.Length > 0) Stat_SubtitleLanguages += ",";
                        Stat_SubtitleLanguages += subLan;
                    }
                    this.StatGroupSubtitleLanguages[ag.AnimeGroupID] = Stat_SubtitleLanguages;

                    UpdateGroupFilterUsingGroup(ag.AnimeGroupID);
                    UpdatePlexAnimeGroup(session, ag, allSeries);
                    UpdateKodiAnimeGroup(session, ag, allSeries);
                }

                ts = DateTime.Now - start;
                logger.Info("GetAllGroups (Contracts) in {0} ms", ts.TotalMilliseconds);

                //UpdateAllAnimeContracts();

            }
            catch (Exception ex)
            {
                logger.ErrorException(ex.ToString(), ex);
            }
        }