PageRenderTime 57ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/JMMServer/JMMServer/StatsCache.cs

https://bitbucket.org/gibwar/jmm-test
C# | 1557 lines | 1207 code | 265 blank | 85 comment | 410 complexity | fc4447bf5046c07d1770fd3d0aad23a5 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using JMMServer.Entities;
  6. using JMMServer.Repositories;
  7. using NLog;
  8. using JMMContracts;
  9. using System.Diagnostics;
  10. using JMMServer.Providers.TraktTV;
  11. using System.Globalization;
  12. using NHibernate;
  13. namespace JMMServer
  14. {
  15. public class StatsCache
  16. {
  17. private static Logger logger = LogManager.GetCurrentClassLogger();
  18. private static StatsCache _instance;
  19. public static StatsCache Instance
  20. {
  21. get
  22. {
  23. if (_instance == null)
  24. {
  25. _instance = new StatsCache();
  26. }
  27. return _instance;
  28. }
  29. }
  30. public List<TraktTVUser> TraktFriendInfo = null;
  31. public List<TraktTVFriendRequest> TraktFriendRequests = null;
  32. public List<TraktTV_Activity> TraktFriendActivityInfo = null;
  33. public Dictionary<int, string> StatGroupCategories = null; // AnimeGroupID / Categories List
  34. public Dictionary<int, string> StatGroupTitles = null; // AnimeGroupID / Titles List
  35. public Dictionary<int, DateTime?> StatGroupAirDate_Min = null; // AnimeGroupID / AirDate_Min
  36. public Dictionary<int, DateTime?> StatGroupAirDate_Max = null; // AnimeGroupID / AirDate_Max
  37. public Dictionary<int, DateTime?> StatGroupEndDate = null; // AnimeGroupID / EndDate
  38. public Dictionary<int, DateTime?> StatGroupSeriesCreatedDate = null; // AnimeGroupID / SeriesCreatedDate
  39. public Dictionary<int, decimal?> StatGroupUserVoteOverall = null; // AnimeGroupID / UserVoteOverall
  40. public Dictionary<int, decimal?> StatGroupUserVotePermanent = null; // AnimeGroupID / UserVotePermanent
  41. public Dictionary<int, decimal?> StatGroupUserVoteTemporary = null; // AnimeGroupID / UserVoteTemporary
  42. public Dictionary<int, bool> StatGroupIsComplete = null; // AnimeGroupID
  43. public Dictionary<int, bool> StatGroupIsFinishedAiring = null; // AnimeGroupID
  44. public Dictionary<int, bool> StatGroupIsCurrentlyAiring = null; // AnimeGroupID
  45. public Dictionary<int, string> StatGroupVideoQuality = null; // AnimeGroupID / Video Quality List
  46. public Dictionary<int, string> StatGroupVideoQualityEpisodes = null; // AnimeGroupID / Video Quality List
  47. public Dictionary<int, string> StatGroupAudioLanguages = null; // AnimeGroupID / audio language List
  48. public Dictionary<int, string> StatGroupSubtitleLanguages = null; // AnimeGroupID / subtitle language List
  49. public Dictionary<int, bool> StatGroupHasTvDB = null; // AnimeGroupID
  50. public Dictionary<int, bool> StatGroupHasMAL = null; // AnimeGroupID
  51. public Dictionary<int, bool> StatGroupHasMovieDB = null; // AnimeGroupID
  52. public Dictionary<int, bool> StatGroupHasMovieDBOrTvDB = null; // AnimeGroupID
  53. public Dictionary<int, int> StatGroupSeriesCount = null; // AnimeGroupID
  54. public Dictionary<int, int> StatGroupEpisodeCount = null; // AnimeGroupID
  55. public Dictionary<int, decimal> StatGroupAniDBRating = null; // AnimeGroupID / AniDBVote
  56. public Dictionary<int, Contract_AniDB_AnimeDetailed> StatAnimeContracts = null; // AnimeID / Contract_AniDB_AnimeDetailed
  57. public Dictionary<int, Dictionary<int, HashSet<int>>> StatUserGroupFilter = null;
  58. public StatsCache()
  59. {
  60. ClearAllData();
  61. }
  62. private void ClearAllData()
  63. {
  64. TraktFriendInfo = new List<TraktTVUser>();
  65. TraktFriendRequests = new List<TraktTVFriendRequest>();
  66. TraktFriendActivityInfo = new List<TraktTV_Activity>();
  67. StatGroupCategories = new Dictionary<int, string>();
  68. StatGroupTitles = new Dictionary<int, string>();
  69. StatGroupAirDate_Min = new Dictionary<int, DateTime?>();
  70. StatGroupAirDate_Max = new Dictionary<int, DateTime?>();
  71. StatGroupEndDate = new Dictionary<int, DateTime?>();
  72. StatGroupSeriesCreatedDate = new Dictionary<int, DateTime?>();
  73. StatGroupUserVoteOverall = new Dictionary<int, decimal?>();
  74. StatGroupUserVotePermanent = new Dictionary<int, decimal?>();
  75. StatGroupUserVoteTemporary = new Dictionary<int, decimal?>();
  76. StatGroupIsComplete = new Dictionary<int, bool>();
  77. StatGroupIsFinishedAiring = new Dictionary<int, bool>();
  78. StatGroupIsCurrentlyAiring = new Dictionary<int, bool>();
  79. StatGroupVideoQuality = new Dictionary<int, string>();
  80. StatGroupVideoQualityEpisodes = new Dictionary<int, string>();
  81. StatGroupAudioLanguages = new Dictionary<int, string>();
  82. StatGroupSubtitleLanguages = new Dictionary<int, string>();
  83. StatGroupHasTvDB = new Dictionary<int, bool>();
  84. StatGroupHasMAL = new Dictionary<int, bool>();
  85. StatGroupHasMovieDB = new Dictionary<int, bool>();
  86. StatGroupHasMovieDBOrTvDB = new Dictionary<int, bool>();
  87. StatGroupSeriesCount = new Dictionary<int, int>();
  88. StatGroupEpisodeCount = new Dictionary<int, int>();
  89. StatGroupAniDBRating = new Dictionary<int, decimal>();
  90. StatAnimeContracts = new Dictionary<int, Contract_AniDB_AnimeDetailed>();
  91. StatUserGroupFilter = new Dictionary<int, Dictionary<int, HashSet<int>>>();
  92. }
  93. public void UpdateGroupFilterUsingGroupFilter(int groupfilter)
  94. {
  95. AnimeGroupRepository repGroups = new AnimeGroupRepository();
  96. AnimeGroup_UserRepository repUserGroups = new AnimeGroup_UserRepository();
  97. JMMUserRepository repUser =new JMMUserRepository();
  98. GroupFilterRepository repGrpFilter=new GroupFilterRepository();
  99. GroupFilter gf = repGrpFilter.GetByID(groupfilter);
  100. if (gf==null)
  101. return;
  102. foreach(JMMUser user in repUser.GetAll())
  103. {
  104. Dictionary<int, HashSet<int>> groupfilters;
  105. if (StatUserGroupFilter.ContainsKey(user.JMMUserID))
  106. groupfilters = StatUserGroupFilter[user.JMMUserID];
  107. else
  108. {
  109. groupfilters = new Dictionary<int, HashSet<int>>();
  110. StatUserGroupFilter.Add(user.JMMUserID, groupfilters);
  111. }
  112. HashSet<int> groups;
  113. if (groupfilters.ContainsKey(groupfilter))
  114. groups = groupfilters[groupfilter];
  115. else
  116. {
  117. groups = new HashSet<int>();
  118. groupfilters.Add(groupfilter, groups);
  119. }
  120. groups.Clear();
  121. List<AnimeGroup> allGrps = repGroups.GetAllTopLevelGroups(); // No Need of subgroups
  122. foreach (AnimeGroup grp in allGrps)
  123. {
  124. AnimeGroup_User userRec = repUserGroups.GetByUserAndGroupID(user.JMMUserID, grp.AnimeGroupID);
  125. if (EvaluateGroupFilter(gf, grp, user, userRec))
  126. groups.Add(grp.AnimeGroupID);
  127. }
  128. }
  129. }
  130. public void UpdateGroupFilterUsingUser(int userid)
  131. {
  132. AnimeGroupRepository repGroups = new AnimeGroupRepository();
  133. AnimeGroup_UserRepository repUserGroups = new AnimeGroup_UserRepository();
  134. JMMUserRepository repUser = new JMMUserRepository();
  135. GroupFilterRepository repGrpFilter = new GroupFilterRepository();
  136. JMMUser user = repUser.GetByID(userid);
  137. if (user == null)
  138. return;
  139. Dictionary<int, HashSet<int>> groupfilters;
  140. if (StatUserGroupFilter.ContainsKey(user.JMMUserID))
  141. groupfilters = StatUserGroupFilter[user.JMMUserID];
  142. else
  143. {
  144. groupfilters = new Dictionary<int, HashSet<int>>();
  145. StatUserGroupFilter.Add(user.JMMUserID, groupfilters);
  146. }
  147. List<GroupFilter> gfs = repGrpFilter.GetAll();
  148. GroupFilter gfgf = new GroupFilter();
  149. gfgf.GroupFilterName = "All";
  150. gfs.Add(gfgf);
  151. foreach(GroupFilter gf in gfs)
  152. {
  153. HashSet<int> groups;
  154. if (groupfilters.ContainsKey(gf.GroupFilterID))
  155. groups = groupfilters[gf.GroupFilterID];
  156. else
  157. {
  158. groups = new HashSet<int>();
  159. groupfilters.Add(gf.GroupFilterID, groups);
  160. }
  161. groups.Clear();
  162. List<AnimeGroup> allGrps = repGroups.GetAllTopLevelGroups(); // No Need of subgroups
  163. foreach (AnimeGroup grp in allGrps)
  164. {
  165. AnimeGroup_User userRec = repUserGroups.GetByUserAndGroupID(user.JMMUserID, grp.AnimeGroupID);
  166. if (EvaluateGroupFilter(gf, grp, user, userRec))
  167. groups.Add(grp.AnimeGroupID);
  168. }
  169. }
  170. }
  171. public void UpdateGroupFilterUsingGroup(int groupid)
  172. {
  173. AnimeGroupRepository repGroups = new AnimeGroupRepository();
  174. AnimeGroup_UserRepository repUserGroups = new AnimeGroup_UserRepository();
  175. JMMUserRepository repUser = new JMMUserRepository();
  176. GroupFilterRepository repGrpFilter = new GroupFilterRepository();
  177. AnimeGroup grp = repGroups.GetByID(groupid);
  178. if (grp.AnimeGroupParentID.HasValue)
  179. return;
  180. foreach (JMMUser user in repUser.GetAll())
  181. {
  182. AnimeGroup_User userRec = repUserGroups.GetByUserAndGroupID(user.JMMUserID, groupid);
  183. Dictionary<int, HashSet<int>> groupfilters;
  184. if (StatUserGroupFilter.ContainsKey(user.JMMUserID))
  185. groupfilters = StatUserGroupFilter[user.JMMUserID];
  186. else
  187. {
  188. groupfilters = new Dictionary<int, HashSet<int>>();
  189. StatUserGroupFilter.Add(user.JMMUserID, groupfilters);
  190. }
  191. List<GroupFilter> gfs = repGrpFilter.GetAll();
  192. GroupFilter gfgf = new GroupFilter();
  193. gfgf.GroupFilterName = "All";
  194. gfs.Add(gfgf);
  195. foreach (GroupFilter gf in gfs)
  196. {
  197. HashSet<int> groups;
  198. if (groupfilters.ContainsKey(gf.GroupFilterID))
  199. groups = groupfilters[gf.GroupFilterID];
  200. else
  201. {
  202. groups = new HashSet<int>();
  203. groupfilters.Add(gf.GroupFilterID, groups);
  204. }
  205. if (groups.Contains(groupid))
  206. groups.Remove(groupid);
  207. if (EvaluateGroupFilter(gf, grp, user, userRec))
  208. groups.Add(grp.AnimeGroupID);
  209. }
  210. }
  211. }
  212. public void UpdateUsingAniDBFile(string hash)
  213. {
  214. try
  215. {
  216. DateTime start = DateTime.Now;
  217. AniDB_FileRepository repAniFile = new AniDB_FileRepository();
  218. AniDB_File anifile = repAniFile.GetByHash(hash);
  219. if (anifile == null) return;
  220. UpdateUsingAnime(anifile.AnimeID);
  221. UpdateAnimeContract(anifile.AnimeID);
  222. TimeSpan ts = DateTime.Now - start;
  223. logger.Info("Updated cached stats file ({0}) in {1} ms", hash, ts.TotalMilliseconds);
  224. }
  225. catch (Exception ex)
  226. {
  227. logger.ErrorException(ex.ToString(), ex);
  228. }
  229. }
  230. public void UpdateUsingAnime(int animeID)
  231. {
  232. using (var session = JMMService.SessionFactory.OpenSession())
  233. {
  234. UpdateUsingAnime(session, animeID);
  235. }
  236. }
  237. public void UpdateUsingAnime(ISession session, int animeID)
  238. {
  239. try
  240. {
  241. AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
  242. AniDB_Anime anime = repAnime.GetByAnimeID(session, animeID);
  243. if (anime == null) return;
  244. AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
  245. AnimeSeries ser = repSeries.GetByAnimeID(session, animeID);
  246. if (ser == null) return;
  247. UpdateUsingSeries(session, ser.AnimeSeriesID);
  248. }
  249. catch (Exception ex)
  250. {
  251. logger.ErrorException(ex.ToString(), ex);
  252. }
  253. }
  254. public void UpdateAnimeContract(ISession session, int animeID)
  255. {
  256. try
  257. {
  258. AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
  259. AniDB_Anime anime = repAnime.GetByAnimeID(session, animeID);
  260. if (anime == null) return;
  261. StatAnimeContracts[anime.AnimeID] = anime.ToContractDetailed(session);
  262. }
  263. catch (Exception ex)
  264. {
  265. logger.ErrorException(ex.ToString(), ex);
  266. }
  267. }
  268. public void UpdateAnimeContract(int animeID)
  269. {
  270. using (var session = JMMService.SessionFactory.OpenSession())
  271. {
  272. UpdateAnimeContract(session, animeID);
  273. }
  274. }
  275. public void UpdateAllAnimeContracts()
  276. {
  277. try
  278. {
  279. DateTime start = DateTime.Now;
  280. AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
  281. using (var session = JMMService.SessionFactory.OpenSession())
  282. {
  283. var series = session
  284. .CreateCriteria(typeof(AnimeSeries))
  285. .List<AnimeSeries>();
  286. List <AnimeSeries> allSeries = new List<AnimeSeries>(series);
  287. foreach (AnimeSeries ser in allSeries)
  288. {
  289. UpdateAnimeContract(session, ser.AniDB_ID);
  290. }
  291. TimeSpan ts = DateTime.Now - start;
  292. logger.Info("Updated All Anime Contracts: {0} in {1} ms", allSeries.Count, ts.TotalMilliseconds);
  293. }
  294. }
  295. catch (Exception ex)
  296. {
  297. logger.ErrorException(ex.ToString(), ex);
  298. }
  299. }
  300. /// <summary>
  301. /// Use whenever a series is added to or removed from a group
  302. /// </summary>
  303. /// <param name="animeSeriesID"></param>
  304. public void UpdateUsingSeries(int animeSeriesID)
  305. {
  306. using (var session = JMMService.SessionFactory.OpenSession())
  307. {
  308. UpdateUsingSeries(session, animeSeriesID);
  309. }
  310. }
  311. public void UpdateUsingSeries(ISession session, int animeSeriesID)
  312. {
  313. try
  314. {
  315. DateTime start = DateTime.Now;
  316. AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
  317. AnimeSeries ser = repSeries.GetByID(session, animeSeriesID);
  318. if (ser == null) return;
  319. foreach (AnimeGroup grp in ser.AllGroupsAbove)
  320. {
  321. UpdateUsingGroup(session, grp.AnimeGroupID);
  322. }
  323. TimeSpan ts = DateTime.Now - start;
  324. logger.Info("Updated cached stats series ({0}) in {1} ms", ser.GetAnime().MainTitle, ts.TotalMilliseconds);
  325. }
  326. catch (Exception ex)
  327. {
  328. logger.ErrorException(ex.ToString(), ex);
  329. }
  330. }
  331. public void UpdateUsingGroup(int animeGroupID)
  332. {
  333. using (var session = JMMService.SessionFactory.OpenSession())
  334. {
  335. UpdateUsingGroup(session, animeGroupID);
  336. }
  337. }
  338. public void UpdateUsingGroup(ISession session, int animeGroupID)
  339. {
  340. try
  341. {
  342. DateTime start = DateTime.Now;
  343. AnimeGroupRepository repGroups = new AnimeGroupRepository();
  344. AnimeGroup thisgrp = repGroups.GetByID(session, animeGroupID);
  345. if (thisgrp == null) return;
  346. AdhocRepository repAdHoc = new AdhocRepository();
  347. // get a list of all the groups including this one and everthing above it the heirarchy
  348. List<AnimeGroup> allgroups = new List<AnimeGroup>();
  349. allgroups.Add(thisgrp);
  350. int? groupID = thisgrp.AnimeGroupParentID;
  351. while (groupID.HasValue)
  352. {
  353. AnimeGroup grpTemp = repGroups.GetByID(session, groupID.Value);
  354. if (grpTemp != null)
  355. {
  356. allgroups.Add(grpTemp);
  357. groupID = grpTemp.AnimeGroupParentID;
  358. }
  359. else
  360. groupID = null;
  361. }
  362. TimeSpan ts = DateTime.Now - start;
  363. logger.Trace("Updating cached stats for GROUP - STEP 1 ({0}) in {1} ms", thisgrp.GroupName, ts.TotalMilliseconds);
  364. start = DateTime.Now;
  365. VideoLocalRepository repVids = new VideoLocalRepository();
  366. CrossRef_File_EpisodeRepository repXrefs = new CrossRef_File_EpisodeRepository();
  367. foreach (AnimeGroup grp in allgroups)
  368. {
  369. StatGroupCategories[grp.AnimeGroupID] = grp.CategoriesString;
  370. StatGroupTitles[grp.AnimeGroupID] = grp.TitlesString;
  371. StatGroupVideoQuality[grp.AnimeGroupID] = grp.VideoQualityString;
  372. ts = DateTime.Now - start;
  373. logger.Trace("Updating cached stats for GROUP - STEP 2 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
  374. start = DateTime.Now;
  375. DateTime? airDate_Min = null;
  376. DateTime? airDate_Max = null;
  377. DateTime? endDate = new DateTime(1980, 1, 1);
  378. DateTime? seriesCreatedDate = null;
  379. bool isComplete = false;
  380. bool hasFinishedAiring = false;
  381. bool isCurrentlyAiring = false;
  382. string videoQualityEpisodes = "";
  383. List<string> audioLanguages = new List<string>();
  384. List<string> subtitleLanguages = new List<string>();
  385. bool hasTvDB = true;
  386. bool hasMAL = true;
  387. bool hasMovieDB = true;
  388. bool hasMovieDBOrTvDB = true;
  389. int seriesCount = 0;
  390. int epCount = 0;
  391. foreach (AnimeSeries series in grp.GetAllSeries(session))
  392. {
  393. seriesCount++;
  394. List<VideoLocal> vidsTemp = repVids.GetByAniDBAnimeID(session, series.AniDB_ID);
  395. List<CrossRef_File_Episode> crossRefs = repXrefs.GetByAnimeID(session, series.AniDB_ID);
  396. Dictionary<int, List<CrossRef_File_Episode>> dictCrossRefs = new Dictionary<int, List<CrossRef_File_Episode>>();
  397. foreach (CrossRef_File_Episode xref in crossRefs)
  398. {
  399. if (!dictCrossRefs.ContainsKey(xref.EpisodeID))
  400. dictCrossRefs[xref.EpisodeID] = new List<CrossRef_File_Episode>();
  401. dictCrossRefs[xref.EpisodeID].Add(xref);
  402. }
  403. Dictionary<string, VideoLocal> dictVids = new Dictionary<string, VideoLocal>();
  404. foreach (VideoLocal vid in vidsTemp)
  405. dictVids[vid.Hash] = vid;
  406. // All Video Quality Episodes
  407. // Try to determine if this anime has all the episodes available at a certain video quality
  408. // e.g. the series has all episodes in blu-ray
  409. // Also look at languages
  410. Dictionary<string, int> vidQualEpCounts = new Dictionary<string,int>(); // video quality, count of episodes
  411. foreach (AnimeEpisode ep in series.GetAnimeEpisodes(session))
  412. {
  413. if (ep.EpisodeTypeEnum != AniDBAPI.enEpisodeType.Episode) continue;
  414. List<VideoLocal> epVids = new List<VideoLocal>();
  415. if (dictCrossRefs.ContainsKey(ep.AniDB_EpisodeID))
  416. {
  417. foreach (CrossRef_File_Episode xref in dictCrossRefs[ep.AniDB_EpisodeID])
  418. {
  419. if (xref.EpisodeID == ep.AniDB_EpisodeID)
  420. {
  421. if (dictVids.ContainsKey(xref.Hash))
  422. epVids.Add(dictVids[xref.Hash]);
  423. }
  424. }
  425. }
  426. List<string> qualityAddedSoFar = new List<string>(); // handle mutliple files of the same quality for one episode
  427. foreach (VideoLocal vid in epVids)
  428. {
  429. AniDB_File anifile = vid.GetAniDBFile(session);
  430. if (anifile == null) continue;
  431. if (!qualityAddedSoFar.Contains(anifile.File_Source))
  432. {
  433. if (!vidQualEpCounts.ContainsKey(anifile.File_Source))
  434. vidQualEpCounts[anifile.File_Source] = 1;
  435. else
  436. vidQualEpCounts[anifile.File_Source]++;
  437. qualityAddedSoFar.Add(anifile.File_Source);
  438. }
  439. }
  440. }
  441. ts = DateTime.Now - start;
  442. logger.Trace("Updating cached stats for GROUP/Series - STEP 3 ({0}/{1}) in {2} ms",grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
  443. start = DateTime.Now;
  444. AniDB_Anime anime = series.GetAnime(session);
  445. epCount = epCount + anime.EpisodeCountNormal;
  446. foreach (KeyValuePair<string, int> kvp in vidQualEpCounts)
  447. {
  448. int index = videoQualityEpisodes.IndexOf(kvp.Key, 0, StringComparison.InvariantCultureIgnoreCase);
  449. if (index > -1) continue; // don't add if we already have it
  450. if (anime.EpisodeCountNormal == kvp.Value)
  451. {
  452. if (videoQualityEpisodes.Length > 0) videoQualityEpisodes += ",";
  453. videoQualityEpisodes += kvp.Key;
  454. }
  455. }
  456. ts = DateTime.Now - start;
  457. logger.Trace("Updating cached stats for GROUP/Series - STEP 4 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
  458. start = DateTime.Now;
  459. // audio languages
  460. Dictionary<int, LanguageStat> dicAudio = repAdHoc.GetAudioLanguageStatsByAnime(session, anime.AnimeID);
  461. foreach (KeyValuePair<int, LanguageStat> kvp in dicAudio)
  462. {
  463. foreach (string lanName in kvp.Value.LanguageNames)
  464. {
  465. if (!audioLanguages.Contains(lanName))
  466. audioLanguages.Add(lanName);
  467. }
  468. }
  469. ts = DateTime.Now - start;
  470. logger.Trace("Updating cached stats for GROUP/Series - STEP 5 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
  471. start = DateTime.Now;
  472. // subtitle languages
  473. Dictionary<int, LanguageStat> dicSubtitle = repAdHoc.GetSubtitleLanguageStatsByAnime(session, anime.AnimeID);
  474. foreach (KeyValuePair<int, LanguageStat> kvp in dicSubtitle)
  475. {
  476. foreach (string lanName in kvp.Value.LanguageNames)
  477. {
  478. if (!subtitleLanguages.Contains(lanName))
  479. subtitleLanguages.Add(lanName);
  480. }
  481. }
  482. ts = DateTime.Now - start;
  483. logger.Trace("Updating cached stats for GROUP/Series - STEP 6 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
  484. start = DateTime.Now;
  485. // Calculate Air Date
  486. DateTime? thisDate = series.AirDate;
  487. if (thisDate.HasValue)
  488. {
  489. if (airDate_Min.HasValue)
  490. {
  491. if (thisDate.Value < airDate_Min.Value) airDate_Min = thisDate;
  492. }
  493. else
  494. airDate_Min = thisDate;
  495. if (airDate_Max.HasValue)
  496. {
  497. if (thisDate.Value > airDate_Max.Value) airDate_Max = thisDate;
  498. }
  499. else
  500. airDate_Max = thisDate;
  501. }
  502. // calculate end date
  503. // if the end date is NULL it actually means it is ongoing, so this is the max possible value
  504. thisDate = series.EndDate;
  505. if (thisDate.HasValue && endDate.HasValue)
  506. {
  507. if (thisDate.Value > endDate.Value) endDate = thisDate;
  508. }
  509. else
  510. endDate = null;
  511. // Note - only one series has to be finished airing to qualify
  512. if (series.EndDate.HasValue && series.EndDate.Value < DateTime.Now)
  513. hasFinishedAiring = true;
  514. // Note - only one series has to be finished airing to qualify
  515. if (!series.EndDate.HasValue || series.EndDate.Value > DateTime.Now)
  516. isCurrentlyAiring = true;
  517. // We evaluate IsComplete as true if
  518. // 1. series has finished airing
  519. // 2. user has all episodes locally
  520. // Note - only one series has to be complete for the group to be considered complete
  521. if (series.EndDate.HasValue)
  522. {
  523. if (series.EndDate.Value < DateTime.Now && series.MissingEpisodeCount == 0 && series.MissingEpisodeCountGroups == 0)
  524. {
  525. isComplete = true;
  526. }
  527. }
  528. // Calculate Series Created Date
  529. thisDate = series.DateTimeCreated;
  530. if (thisDate.HasValue)
  531. {
  532. if (seriesCreatedDate.HasValue)
  533. {
  534. if (thisDate.Value < seriesCreatedDate.Value) seriesCreatedDate = thisDate;
  535. }
  536. else
  537. seriesCreatedDate = thisDate;
  538. }
  539. ts = DateTime.Now - start;
  540. logger.Trace("Updating cached stats for GROUP/Series - STEP 7 ({0}/{1}) in {2} ms", grp.GroupName, series.AnimeSeriesID, ts.TotalMilliseconds);
  541. start = DateTime.Now;
  542. // for the group, if any of the series don't have a tvdb link
  543. // we will consider the group as not having a tvdb link
  544. if (series.GetCrossRefTvDB() == null) hasTvDB = false;
  545. if (series.CrossRefMovieDB == null) hasMovieDB = false;
  546. if (series.CrossRefMAL == null) hasMAL = false;
  547. if (series.GetCrossRefTvDB() == null && series.CrossRefMovieDB == null) hasMovieDBOrTvDB = false;
  548. }
  549. StatGroupIsComplete[grp.AnimeGroupID] = isComplete;
  550. StatGroupIsFinishedAiring[grp.AnimeGroupID] = hasFinishedAiring;
  551. StatGroupIsCurrentlyAiring[grp.AnimeGroupID] = isCurrentlyAiring;
  552. StatGroupHasTvDB[grp.AnimeGroupID] = hasTvDB;
  553. StatGroupHasMAL[grp.AnimeGroupID] = hasMAL;
  554. StatGroupHasMovieDB[grp.AnimeGroupID] = hasMovieDB;
  555. StatGroupHasMovieDBOrTvDB[grp.AnimeGroupID] = hasMovieDBOrTvDB;
  556. StatGroupSeriesCount[grp.AnimeGroupID] = seriesCount;
  557. StatGroupEpisodeCount[grp.AnimeGroupID] = epCount;
  558. StatGroupVideoQualityEpisodes[grp.AnimeGroupID] = videoQualityEpisodes;
  559. StatGroupAirDate_Min[grp.AnimeGroupID] = airDate_Min;
  560. StatGroupAirDate_Max[grp.AnimeGroupID] = airDate_Max;
  561. StatGroupEndDate[grp.AnimeGroupID] = endDate;
  562. StatGroupSeriesCreatedDate[grp.AnimeGroupID] = seriesCreatedDate;
  563. StatGroupUserVoteOverall[grp.AnimeGroupID] = grp.UserVote;
  564. StatGroupUserVotePermanent[grp.AnimeGroupID] = grp.UserVotePermanent;
  565. StatGroupUserVoteTemporary[grp.AnimeGroupID] = grp.UserVoteTemporary;
  566. StatGroupAniDBRating[grp.AnimeGroupID] = grp.AniDBRating;
  567. ts = DateTime.Now - start;
  568. logger.Trace("Updating cached stats for GROUP - STEP 8 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
  569. start = DateTime.Now;
  570. string Stat_AudioLanguages = "";
  571. foreach (string audioLan in audioLanguages)
  572. {
  573. if (Stat_AudioLanguages.Length > 0) Stat_AudioLanguages += ",";
  574. Stat_AudioLanguages += audioLan;
  575. }
  576. this.StatGroupAudioLanguages[grp.AnimeGroupID] = Stat_AudioLanguages;
  577. string Stat_SubtitleLanguages = "";
  578. foreach (string subLan in subtitleLanguages)
  579. {
  580. if (Stat_SubtitleLanguages.Length > 0) Stat_SubtitleLanguages += ",";
  581. Stat_SubtitleLanguages += subLan;
  582. }
  583. this.StatGroupSubtitleLanguages[grp.AnimeGroupID] = Stat_SubtitleLanguages;
  584. ts = DateTime.Now - start;
  585. logger.Trace("Updating cached stats for GROUP - STEP 9 ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
  586. start = DateTime.Now;
  587. UpdateGroupFilterUsingGroup(grp.AnimeGroupID);
  588. ts = DateTime.Now - start;
  589. logger.Trace("Updating cached stats for GROUP - END ({0}) in {1} ms", grp.GroupName, ts.TotalMilliseconds);
  590. }
  591. }
  592. catch (Exception ex)
  593. {
  594. logger.ErrorException(ex.ToString(), ex);
  595. }
  596. }
  597. public void InitStats()
  598. {
  599. try
  600. {
  601. DateTime start = DateTime.Now;
  602. ClearAllData();
  603. #region Get the data
  604. AnimeGroupRepository repGroups = new AnimeGroupRepository();
  605. AniDB_AnimeRepository repAnime = new AniDB_AnimeRepository();
  606. AnimeSeriesRepository repSeries = new AnimeSeriesRepository();
  607. AniDB_CategoryRepository repCats = new AniDB_CategoryRepository();
  608. AniDB_Anime_CategoryRepository repAnimeCat = new AniDB_Anime_CategoryRepository();
  609. AniDB_Anime_TitleRepository repTitles = new AniDB_Anime_TitleRepository();
  610. List<AnimeGroup> allGrps = repGroups.GetAll();
  611. Dictionary<int, AnimeGroup> allGroupsDict = new Dictionary<int, AnimeGroup>();
  612. foreach (AnimeGroup agrp in allGrps)
  613. allGroupsDict[agrp.AnimeGroupID] = agrp;
  614. TimeSpan ts = DateTime.Now - start;
  615. logger.Info("Get All GROUPS (Database) in {0} ms", ts.TotalMilliseconds);
  616. // anime
  617. start = DateTime.Now;
  618. List<AniDB_Anime> allAnime = repAnime.GetAll();
  619. Dictionary<int, AniDB_Anime> allAnimeDict = new Dictionary<int, AniDB_Anime>();
  620. foreach (AniDB_Anime anime in allAnime)
  621. allAnimeDict[anime.AnimeID] = anime;
  622. ts = DateTime.Now - start;
  623. logger.Info("Get All ANIME (Database) in {0} ms", ts.TotalMilliseconds);
  624. // categories
  625. start = DateTime.Now;
  626. List<AniDB_Category> allCatgeories = repCats.GetAll();
  627. Dictionary<int, AniDB_Category> allCatgeoriesDict = new Dictionary<int, AniDB_Category>();
  628. foreach (AniDB_Category cat in allCatgeories)
  629. allCatgeoriesDict[cat.CategoryID] = cat;
  630. List<AniDB_Anime_Category> allAnimeCatgeories = repAnimeCat.GetAll();
  631. Dictionary<int, List<int>> allAnimeCatgeoriesDict = new Dictionary<int, List<int>>(); // animeid / list of category id's
  632. foreach (AniDB_Anime_Category aniCat in allAnimeCatgeories)
  633. {
  634. if (!allAnimeCatgeoriesDict.ContainsKey(aniCat.AnimeID))
  635. allAnimeCatgeoriesDict[aniCat.AnimeID] = new List<int>();
  636. allAnimeCatgeoriesDict[aniCat.AnimeID].Add(aniCat.CategoryID);
  637. }
  638. ts = DateTime.Now - start;
  639. logger.Info("Get All CATEGORIES (Database) in {0} ms", ts.TotalMilliseconds);
  640. // titles
  641. start = DateTime.Now;
  642. List<AniDB_Anime_Title> allTitles = repTitles.GetAll();
  643. Dictionary<int, List<AniDB_Anime_Title>> allTitlesDict = new Dictionary<int, List<AniDB_Anime_Title>>(); // animeid / list of titles
  644. foreach (AniDB_Anime_Title aniTitle in allTitles)
  645. {
  646. if (!allTitlesDict.ContainsKey(aniTitle.AnimeID))
  647. allTitlesDict[aniTitle.AnimeID] = new List<AniDB_Anime_Title>();
  648. allTitlesDict[aniTitle.AnimeID].Add(aniTitle);
  649. }
  650. ts = DateTime.Now - start;
  651. logger.Info("Get All TITLES (Database) in {0} ms", ts.TotalMilliseconds);
  652. // user votes
  653. start = DateTime.Now;
  654. AniDB_VoteRepository repVotes = new AniDB_VoteRepository();
  655. List<AniDB_Vote> allVotes = repVotes.GetAll();
  656. ts = DateTime.Now - start;
  657. logger.Info("Get All VOTES (Database) in {0} ms", ts.TotalMilliseconds);
  658. // video quality
  659. start = DateTime.Now;
  660. AdhocRepository rep = new AdhocRepository();
  661. Dictionary<int, string> allVidQuality = rep.GetAllVideoQualityByGroup();
  662. ts = DateTime.Now - start;
  663. logger.Info("Get VIDEO QUALITY STATS (Database) in {0} ms", ts.TotalMilliseconds);
  664. // video quality episode stats
  665. start = DateTime.Now;
  666. Dictionary<int, AnimeVideoQualityStat> dictStats = rep.GetEpisodeVideoQualityStatsByAnime();
  667. ts = DateTime.Now - start;
  668. logger.Info("Get VIDEO QUALITY EPISODE STATS (Database) in {0} ms", ts.TotalMilliseconds);
  669. // audio and subtitle language stats
  670. start = DateTime.Now;
  671. Dictionary<int, LanguageStat> dictAudioStats = rep.GetAudioLanguageStatsForAnime();
  672. Dictionary<int, LanguageStat> dictSubtitleStats = rep.GetSubtitleLanguageStatsForAnime();
  673. ts = DateTime.Now - start;
  674. logger.Info("Get LANGUAGE STATS (Database) in {0} ms", ts.TotalMilliseconds);
  675. start = DateTime.Now;
  676. List<AnimeSeries> allSeries = repSeries.GetAll();
  677. ts = DateTime.Now - start;
  678. logger.Info("Get All Series (Database) in {0} ms", ts.TotalMilliseconds);
  679. // TvDB
  680. start = DateTime.Now;
  681. CrossRef_AniDB_TvDBRepository repCrossRef = new CrossRef_AniDB_TvDBRepository();
  682. List<CrossRef_AniDB_TvDB> allCrossRefs = repCrossRef.GetAll();
  683. List<int> animeWithTvDBCrossRef = new List<int>();
  684. foreach (CrossRef_AniDB_TvDB xref in allCrossRefs)
  685. {
  686. if (!animeWithTvDBCrossRef.Contains(xref.AnimeID)) animeWithTvDBCrossRef.Add(xref.AnimeID);
  687. }
  688. ts = DateTime.Now - start;
  689. logger.Info("Get All AniDB->TvDB Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);
  690. // MovieDB
  691. start = DateTime.Now;
  692. CrossRef_AniDB_OtherRepository repOtherCrossRef = new CrossRef_AniDB_OtherRepository();
  693. List<CrossRef_AniDB_Other> allOtherCrossRefs = repOtherCrossRef.GetAll();
  694. List<int> animeWithMovieCrossRef = new List<int>();
  695. foreach (CrossRef_AniDB_Other xref in allOtherCrossRefs)
  696. {
  697. if (!animeWithMovieCrossRef.Contains(xref.AnimeID) && xref.CrossRefType == (int)CrossRefType.MovieDB)
  698. animeWithMovieCrossRef.Add(xref.AnimeID);
  699. }
  700. ts = DateTime.Now - start;
  701. logger.Info("Get All AniDB->MovieDB Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);
  702. // MAL
  703. start = DateTime.Now;
  704. CrossRef_AniDB_MALRepository repMALCrossRef = new CrossRef_AniDB_MALRepository();
  705. List<CrossRef_AniDB_MAL> allMALCrossRefs = repMALCrossRef.GetAll();
  706. List<int> animeWithMALCrossRef = new List<int>();
  707. foreach (CrossRef_AniDB_MAL xref in allMALCrossRefs)
  708. {
  709. if (!animeWithMALCrossRef.Contains(xref.AnimeID))
  710. animeWithMALCrossRef.Add(xref.AnimeID);
  711. }
  712. ts = DateTime.Now - start;
  713. logger.Info("Get All AniDB->MAL Cross Refs (Database) in {0} ms", ts.TotalMilliseconds);
  714. #endregion
  715. start = DateTime.Now;
  716. foreach (AnimeGroup ag in allGrps)
  717. {
  718. // get all the series for this group
  719. List<AnimeSeries> seriesForGroup = new List<AnimeSeries>();
  720. GetAnimeSeriesRecursive(ag, ref seriesForGroup, allSeries, allGroupsDict);
  721. if (ag.AnimeGroupID == 166)
  722. {
  723. Console.Write("");
  724. }
  725. DateTime? Stat_AirDate_Min = null;
  726. DateTime? Stat_AirDate_Max = null;
  727. DateTime? Stat_EndDate = new DateTime(1980, 1, 1);
  728. DateTime? Stat_SeriesCreatedDate = null;
  729. bool isComplete = false;
  730. bool hasFinishedAiring = false;
  731. bool isCurrentlyAiring = false;
  732. List<int> categoryIDList = new List<int>();
  733. List<string> audioLanguageList = new List<string>();
  734. List<string> subtitleLanguageList = new List<string>();
  735. string Stat_AllTitles = "";
  736. string Stat_AllCategories = "";
  737. string Stat_AllVideoQualityEpisodes = "";
  738. decimal totalVotesPerm = 0, totalVotesTemp = 0, totalVotes = 0;
  739. int countVotesPerm = 0, countVotesTemp = 0, countVotes = 0;
  740. bool hasTvDB = true;
  741. bool hasMAL = true;
  742. bool hasMovieDB = true;
  743. bool hasMovieDBOrTvDB = true;
  744. int seriesCount = 0;
  745. int epCount = 0;
  746. foreach (AnimeSeries series in seriesForGroup)
  747. {
  748. seriesCount++;
  749. if (allAnimeDict.ContainsKey(series.AniDB_ID))
  750. {
  751. AniDB_Anime thisAnime = allAnimeDict[series.AniDB_ID];
  752. epCount = epCount + thisAnime.EpisodeCountNormal;
  753. // All Video Quality Episodes
  754. // Try to determine if this anime has all the episodes available at a certain video quality
  755. // e.g. the series has all episodes in blu-ray
  756. if (dictStats.ContainsKey(series.AniDB_ID))
  757. {
  758. if (series.AniDB_ID == 7656)
  759. {
  760. Debug.Print("");
  761. }
  762. AnimeVideoQualityStat stat = dictStats[series.AniDB_ID];
  763. foreach (KeyValuePair<string, int> kvp in stat.VideoQualityEpisodeCount)
  764. {
  765. if (kvp.Value >= thisAnime.EpisodeCountNormal)
  766. {
  767. if (Stat_AllVideoQualityEpisodes.Length > 0) Stat_AllVideoQualityEpisodes += ",";
  768. Stat_AllVideoQualityEpisodes += kvp.Key;
  769. }
  770. }
  771. }
  772. // Calculate Air Date
  773. DateTime? thisDate = thisAnime.AirDate;
  774. if (thisDate.HasValue)
  775. {
  776. if (Stat_AirDate_Min.HasValue)
  777. {
  778. if (thisDate.Value < Stat_AirDate_Min.Value) Stat_AirDate_Min = thisDate;
  779. }
  780. else
  781. Stat_AirDate_Min = thisDate;
  782. if (Stat_AirDate_Max.HasValue)
  783. {
  784. if (thisDate.Value > Stat_AirDate_Max.Value) Stat_AirDate_Max = thisDate;
  785. }
  786. else
  787. Stat_AirDate_Max = thisDate;
  788. }
  789. // calculate end date
  790. // if the end date is NULL it actually means it is ongoing, so this is the max possible value
  791. thisDate = thisAnime.EndDate;
  792. if (thisDate.HasValue && Stat_EndDate.HasValue)
  793. {
  794. if (thisDate.Value > Stat_EndDate.Value) Stat_EndDate = thisDate;
  795. }
  796. else
  797. Stat_EndDate = null;
  798. // Calculate Series Created Date
  799. thisDate = series.DateTimeCreated;
  800. if (thisDate.HasValue)
  801. {
  802. if (Stat_SeriesCreatedDate.HasValue)
  803. {
  804. if (thisDate.Value < Stat_SeriesCreatedDate.Value) Stat_SeriesCreatedDate = thisDate;
  805. }
  806. else
  807. Stat_SeriesCreatedDate = thisDate;
  808. }
  809. if (series.AniDB_ID == 2369)
  810. Debug.Write("Test");
  811. // Note - only one series has to be finished airing to qualify
  812. if (thisAnime.EndDate.HasValue && thisAnime.EndDate.Value < DateTime.Now)
  813. hasFinishedAiring = true;
  814. // Note - only one series has to be currently airing to qualify
  815. if (!thisAnime.EndDate.HasValue || thisAnime.EndDate.Value > DateTime.Now)
  816. isCurrentlyAiring = true;
  817. // We evaluate IsComplete as true if
  818. // 1. series has finished airing
  819. // 2. user has all episodes locally
  820. // Note - only one series has to be complete for the group to be considered complete
  821. if (thisAnime.EndDate.HasValue)
  822. {
  823. if (thisAnime.EndDate.Value < DateTime.Now && series.MissingEpisodeCount == 0 && series.MissingEpisodeCountGroups == 0)
  824. {
  825. isComplete = true;
  826. }
  827. }
  828. // get categories
  829. if (allAnimeCatgeoriesDict.ContainsKey(series.AniDB_ID))
  830. {
  831. foreach (int catID in allAnimeCatgeoriesDict[series.AniDB_ID])
  832. {
  833. if (!categoryIDList.Contains(catID)) categoryIDList.Add(catID);
  834. }
  835. }
  836. // get audio languages
  837. if (dictAudioStats.ContainsKey(series.AniDB_ID))
  838. {
  839. foreach (string lanName in dictAudioStats[series.AniDB_ID].LanguageNames)
  840. {
  841. if (!audioLanguageList.Contains(lanName)) audioLanguageList.Add(lanName);
  842. }
  843. }
  844. // get subtitle languages
  845. if (dictSubtitleStats.ContainsKey(series.AniDB_ID))
  846. {
  847. foreach (string lanName in dictSubtitleStats[series.AniDB_ID].LanguageNames)
  848. {
  849. if (!subtitleLanguageList.Contains(lanName)) subtitleLanguageList.Add(lanName);
  850. }
  851. }
  852. // get titles
  853. if (allTitlesDict.ContainsKey(series.AniDB_ID))
  854. {
  855. foreach (AniDB_Anime_Title title in allTitlesDict[series.AniDB_ID])
  856. {
  857. if (Stat_AllTitles.Length > 0) Stat_AllTitles += ",";
  858. Stat_AllTitles += title.Title;
  859. }
  860. }
  861. // get votes
  862. foreach (AniDB_Vote vote in allVotes)
  863. {
  864. if (vote.EntityID == series.AniDB_ID && (vote.VoteType == (int)AniDBVoteType.Anime || vote.VoteType == (int)AniDBVoteType.AnimeTemp))
  865. {
  866. countVotes++;
  867. totalVotes += (decimal)vote.VoteValue;
  868. if (vote.VoteType == (int)AniDBVoteType.Anime)
  869. {
  870. countVotesPerm++;
  871. totalVotesPerm += (decimal)vote.VoteValue;
  872. }
  873. if (vote.VoteType == (int)AniDBVoteType.AnimeTemp)
  874. {
  875. countVotesTemp++;
  876. totalVotesTemp += (decimal)vote.VoteValue;
  877. }
  878. break;
  879. }
  880. }
  881. }
  882. // for the group, if any of the series don't have a tvdb link
  883. // we will consider the group as not having a tvdb link
  884. if (!animeWithTvDBCrossRef.Contains(series.AniDB_ID)) hasTvDB = false;
  885. if (!animeWithMovieCrossRef.Contains(series.AniDB_ID)) hasMovieDB = false;
  886. if (!animeWithMALCrossRef.Contains(series.AniDB_ID)) hasMAL = false;
  887. if (!animeWithTvDBCrossRef.Contains(series.AniDB_ID) && !animeWithMovieCrossRef.Contains(series.AniDB_ID)) hasMovieDBOrTvDB = false;
  888. }
  889. if (allVidQuality.ContainsKey(ag.AnimeGroupID))
  890. StatGroupVideoQuality[ag.AnimeGroupID] = allVidQuality[ag.AnimeGroupID];
  891. else
  892. StatGroupVideoQuality[ag.AnimeGroupID] = "";
  893. StatGroupVideoQualityEpisodes[ag.AnimeGroupID] = Stat_AllVideoQualityEpisodes;
  894. StatGroupIsComplete[ag.AnimeGroupID] = isComplete;
  895. StatGroupIsFinishedAiring[ag.AnimeGroupID] = hasFinishedAiring;
  896. StatGroupIsCurrentlyAiring[ag.AnimeGroupID] = isCurrentlyAiring;
  897. StatGroupSeriesCount[ag.AnimeGroupID] = seriesCount;
  898. StatGroupEpisodeCount[ag.AnimeGroupID] = epCount;
  899. StatGroupTitles[ag.AnimeGroupID] = Stat_AllTitles;
  900. StatGroupAirDate_Max[ag.AnimeGroupID] = Stat_AirDate_Max;
  901. StatGroupAirDate_Min[ag.AnimeGroupID] = Stat_AirDate_Min;
  902. StatGroupEndDate[ag.AnimeGroupID] = Stat_EndDate;
  903. StatGroupSeriesCreatedDate[ag.AnimeGroupID] = Stat_SeriesCreatedDate;
  904. StatGroupHasTvDB[ag.AnimeGroupID] = hasTvDB;
  905. StatGroupHasMAL[ag.AnimeGroupID] = hasMAL;
  906. StatGroupHasMovieDB[ag.AnimeGroupID] = hasMovieDB;
  907. StatGroupHasMovieDBOrTvDB[ag.AnimeGroupID] = hasMovieDBOrTvDB;
  908. decimal? Stat_UserVoteOverall = null;
  909. if (countVotes > 0)
  910. Stat_UserVoteOverall = totalVotes / (decimal)countVotes / (decimal)100;
  911. StatGroupUserVoteOverall[ag.AnimeGroupID] = Stat_UserVoteOverall;
  912. decimal? Stat_UserVotePermanent = null;
  913. if (countVotesPerm > 0)
  914. Stat_UserVotePermanent = totalVotesPerm / (decimal)countVotesPerm / (decimal)100;
  915. StatGroupUserVotePermanent[ag.AnimeGroupID] = Stat_UserVotePermanent;
  916. decimal? Stat_UserVoteTemporary = null;
  917. if (countVotesTemp > 0)
  918. Stat_UserVoteTemporary = totalVotesTemp / (decimal)countVotesTemp / (decimal)100;
  919. StatGroupUserVoteTemporary[ag.AnimeGroupID] = Stat_UserVoteTemporary;
  920. StatGroupAniDBRating[ag.AnimeGroupID] = ag.AniDBRating;
  921. Stat_AllCategories = "";
  922. foreach (int catID in categoryIDList)
  923. {
  924. if (!allCatgeoriesDict.ContainsKey(catID)) continue;
  925. string catName = allCatgeoriesDict[catID].CategoryName;
  926. if (Stat_AllCategories.Length > 0)
  927. Stat_AllCategories += "|";
  928. Stat_AllCategories += catName;
  929. }
  930. this.StatGroupCategories[ag.AnimeGroupID] = Stat_AllCategories;
  931. string Stat_AudioLanguages = "";
  932. foreach (string audioLan in audioLanguageList)
  933. {
  934. if (Stat_AudioLanguages.Length > 0) Stat_AudioLanguages += ",";
  935. Stat_AudioLanguages += audioLan;
  936. }
  937. this.StatGroupAudioLanguages[ag.AnimeGroupID] = Stat_AudioLanguages;
  938. string Stat_SubtitleLanguages = "";
  939. foreach (string subLan in subtitleLanguageList)
  940. {
  941. if (Stat_SubtitleLanguages.Length > 0) Stat_SubtitleLanguages += ",";
  942. Stat_SubtitleLanguages += subLan;
  943. }
  944. this.StatGroupSubtitleLanguages[ag.AnimeGroupID] = Stat_SubtitleLanguages;
  945. UpdateGroupFilterUsingGroup(ag.AnimeGroupID);
  946. }
  947. ts = DateTime.Now - start;
  948. logger.Info("GetAllGroups (Contracts) in {0} ms", ts.TotalMilliseconds);
  949. //UpdateAllAnimeContracts();
  950. }
  951. catch (Exception ex)
  952. {
  953. logger.ErrorException(ex.ToString(), ex);
  954. }
  955. }
  956. private static void GetAnimeSeriesRecursive(AnimeGroup grp, ref List<AnimeSeries> seriesList, List<AnimeSeries> allSeries, Dictionary<int, AnimeGroup> allGroupsDict)
  957. {
  958. // get the series for this group
  959. List<AnimeSeries> thisSeries = new List<AnimeSeries>();
  960. foreach (AnimeSeries ser in allSeries)
  961. if (ser.AnimeGroupID == grp.AnimeGroupID) seriesList.Add(ser);
  962. foreach (KeyValuePair<int, AnimeGroup> kvp in allGroupsDict)
  963. {
  964. if (kvp.Value.AnimeGroupParentID.HasValue && kvp.Value.AnimeGroupParentID.Value == grp.AnimeGroupID)
  965. {
  966. GetAnimeSeriesRecursive(kvp.Value, ref seriesList, allSeries, allGroupsDict);
  967. }
  968. }
  969. /*foreach (AnimeGroup childGroup in grp.ChildGroups)
  970. {
  971. GetAnimeSeriesRecursive(childGroup, ref seriesList, allSeries, allGroupsDict);
  972. }*/
  973. }
  974. public bool EvaluateGroupFilter(GroupFilter gf, AnimeGroup grp, JMMUser curUser, AnimeGroup_User userRec)
  975. {
  976. // sub groups don't count
  977. if (grp.AnimeGroupParentID.HasValue) return false;
  978. // make sure the user has not filtered this out
  979. if (!curUser.AllowedGroup(grp, userRec)) return false;
  980. // first check for anime groups which are included exluded every time
  981. foreach (GroupFilterCondition gfc in gf.FilterConditions)
  982. {
  983. if (gfc.ConditionTypeEnum != GroupFilterConditionType.AnimeGroup) continue;
  984. int groupID = 0;
  985. int.TryParse(gfc.ConditionParameter, out groupID);
  986. if (groupID == 0) break;
  987. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Equals)
  988. if (groupID == grp.AnimeGroupID) return true;
  989. if (gfc.ConditionOperatorEnum == GroupFilterOperator.NotEquals)
  990. if (groupID == grp.AnimeGroupID) return false;
  991. }
  992. NumberStyles style = NumberStyles.Number;
  993. CultureInfo culture = CultureInfo.CreateSpecificCulture("en-GB");
  994. if (gf.BaseCondition == (int)GroupFilterBaseCondition.Exclude) return false;
  995. Contract_AnimeGroup contractGroup = grp.ToContract(userRec);
  996. // now check other conditions
  997. foreach (GroupFilterCondition gfc in gf.FilterConditions)
  998. {
  999. switch (gfc.ConditionTypeEnum)
  1000. {
  1001. case GroupFilterConditionType.Favourite:
  1002. if (userRec == null) return false;
  1003. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && userRec.IsFave == 0) return false;
  1004. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && userRec.IsFave == 1) return false;
  1005. break;
  1006. case GroupFilterConditionType.MissingEpisodes:
  1007. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && grp.HasMissingEpisodesAny == false) return false;
  1008. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && grp.HasMissingEpisodesAny == true) return false;
  1009. break;
  1010. case GroupFilterConditionType.MissingEpisodesCollecting:
  1011. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && grp.HasMissingEpisodesGroups == false) return false;
  1012. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && grp.HasMissingEpisodesGroups == true) return false;
  1013. break;
  1014. case GroupFilterConditionType.HasWatchedEpisodes:
  1015. if (userRec == null) return false;
  1016. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && userRec.AnyFilesWatched == false) return false;
  1017. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && userRec.AnyFilesWatched == true) return false;
  1018. break;
  1019. case GroupFilterConditionType.HasUnwatchedEpisodes:
  1020. if (userRec == null) return false;
  1021. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && userRec.HasUnwatchedFiles == false) return false;
  1022. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && userRec.HasUnwatchedFiles == true) return false;
  1023. break;
  1024. case GroupFilterConditionType.AssignedTvDBInfo:
  1025. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_HasTvDBLink == false) return false;
  1026. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_HasTvDBLink == true) return false;
  1027. break;
  1028. case GroupFilterConditionType.AssignedMALInfo:
  1029. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_HasMALLink == false) return false;
  1030. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_HasMALLink == true) return false;
  1031. break;
  1032. case GroupFilterConditionType.AssignedMovieDBInfo:
  1033. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_HasMovieDBLink == false) return false;
  1034. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_HasMovieDBLink == true) return false;
  1035. break;
  1036. case GroupFilterConditionType.AssignedTvDBOrMovieDBInfo:
  1037. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_HasMovieDBOrTvDBLink == false) return false;
  1038. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_HasMovieDBOrTvDBLink == true) return false;
  1039. break;
  1040. case GroupFilterConditionType.CompletedSeries:
  1041. /*if (grp.IsComplete != grp.Stat_IsComplete)
  1042. {
  1043. Debug.Print("IsComplete DIFF {0}", grp.GroupName);
  1044. }*/
  1045. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_IsComplete == false) return false;
  1046. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_IsComplete == true) return false;
  1047. break;
  1048. case GroupFilterConditionType.FinishedAiring:
  1049. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_HasFinishedAiring == false) return false;
  1050. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_IsCurrentlyAiring == false) return false;
  1051. break;
  1052. case GroupFilterConditionType.UserVoted:
  1053. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_UserVotePermanent.HasValue == false) return false;
  1054. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_UserVotePermanent.HasValue == true) return false;
  1055. break;
  1056. case GroupFilterConditionType.UserVotedAny:
  1057. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Include && contractGroup.Stat_UserVoteOverall.HasValue == false) return false;
  1058. if (gfc.ConditionOperatorEnum == GroupFilterOperator.Exclude && contractGroup.Stat_UserVoteOverall.HasValue == true) return false;
  1059. break;
  1060. case GroupFilterConditionType.AirDate:
  1061. DateTime filterDate;
  1062. if (gfc.ConditionOperatorEnum == GroupFilterOperator.LastXDays)
  1063. {
  1064. int days = 0;
  1065. int.TryParse(gfc.ConditionParameter, out days);
  1066. filterDate = DateTime.Today.AddDays(0 - days);
  1067. }
  1068. else
  1069. filterDate = GetDateFromString(gfc.ConditionParameter);
  1070. if (gfc.ConditionOperatorEnum == GroupFilterOperator.GreaterThan || gfc.ConditionOperatorEnum == GroupFilterOperator.LastXDays)
  1071. {
  1072. if (!contractGroup.Stat_AirDate_Min.HasValue || !contractGroup.Stat_AirDate_Max.HasValue) return false;
  1073. if (contractGroup.Stat_AirDate_Max.Value < filterDate) return false;
  1074. }

Large files files are truncated, but you can click here to view the full file