private void InsertSort(ref LinkedList <MixerClip> list, MixerClip c, ClipMineSortTypes type) { LinkedListNode <MixerClip> node = list.First; while (node != null) { bool result = false; switch (type) { case ClipMineSortTypes.MostRecent: result = c.UploadDate > node.Value.UploadDate; break; case ClipMineSortTypes.MixTokRank: result = c.MixTokRank > node.Value.MixTokRank; break; default: case ClipMineSortTypes.ViewCount: result = c.ViewCount > node.Value.ViewCount; break; } if (result) { list.AddBefore(node, c); return; } node = node.Next; } list.AddLast(c); }
public IActionResult Get(int sortType, int?limit, string fromTime, string toTime, int?ViewCountMin, int?channelId, string channelName, bool?isLive, bool?partnered, string gameTitle, int?gameId, int?hypeZoneChannelId, string language) { DateTime start = DateTime.Now; // Setup the limit values int l = limit.HasValue ? limit.Value : 50; // If we get time ranges, parse them. DateTime?from = null; DateTime?to = null; if (!String.IsNullOrWhiteSpace(fromTime)) { from = ParseTime(fromTime); if (from == null) { return(BadRequest("Invalid time format. We accept unix time, anything C# DateTime can parse, or formats like `1d`, `5h`, etc.")); } } if (!String.IsNullOrWhiteSpace(toTime)) { to = ParseTime(toTime); if (to == null) { return(BadRequest("Invalid time format. We accept unix time, anything C# DateTime can parse, or formats like `1d`, `5h`, etc.")); } } // Figure out the sort ClipMineSortTypes sort = ClipMineSortTypes.ViewCount; switch (sortType) { case 0: sort = ClipMineSortTypes.ViewCount; break; case 1: sort = ClipMineSortTypes.MixTokRank; break; case 2: sort = ClipMineSortTypes.MostRecent; break; default: return(BadRequest("Invalid sort type, ViewCount=0, MixTockRank=1")); } // Get the results. var list = Program.s_ClipMine.GetClips(sort, l, from, to, ViewCountMin, channelId, channelName, hypeZoneChannelId, isLive, partnered, gameTitle, gameId, language); Logger.Info($"ClipMine call took {(DateTime.Now - start).TotalMilliseconds}ms"); return(Ok(list)); }
private LinkedList <MixerClip> BuildList(Dictionary <string, MixerClip> db, ClipMineSortTypes type, string indexType) { int count = 0; LinkedList <MixerClip> tempList = new LinkedList <MixerClip>(); foreach (KeyValuePair <string, MixerClip> p in db) { InsertSort(ref tempList, p.Value, type); // Do to issues with API perf while we are sorting, we need to manually yield the thread to // give the APIs time to process. count++; if (count % 1000 == 0) { SetStatus($"Cooking {indexType} [{String.Format("{0:n0}", count)}/{String.Format("{0:n0}", db.Count)}]..."); Thread.Sleep(5); } } return(tempList); }
public List <MixerClip> GetClips(ClipMineSortTypes sortType, int limit = 100, DateTime?fromTime = null, DateTime?toTime = null, int?ViewCountMin = null, int?channelIdFilter = null, string channelName = null, int?hypeZoneChannelId = null, bool?currentlyLive = null, bool?partnered = null, string gameTitle = null, int?gameId = null, string languageFilter = null) { // Get the pre-sorted list we want. LinkedList <MixerClip> list; object lockObj; switch (sortType) { default: case ClipMineSortTypes.ViewCount: list = m_viewCountSortedList; lockObj = m_viewCountSortedLock; break; case ClipMineSortTypes.MixTokRank: list = m_mixTockSortedList; lockObj = m_mixTockSortedLock; break; case ClipMineSortTypes.MostRecent: list = m_mostRecentList; lockObj = m_mostRecentSortedLock; break; } List <MixerClip> output = new List <MixerClip>(); // Lock the list so it doesn't change while we are using it. lock (lockObj) { // Go through the current sorted list from the highest to the lowest. // Apply the filtering and then build the output list. LinkedListNode <MixerClip> node = list.First; while (output.Count < limit && node != null) { // Get the node and advance here, becasue this will continue early // if the search filters it out. MixerClip c = node.Value; node = node.Next; if (channelIdFilter.HasValue) { // Check if this is the channel we want. if (c.Channel.Id != channelIdFilter.Value) { continue; } } if (!String.IsNullOrWhiteSpace(channelName)) { // Check if the channel name has the current filter. if (c.Channel.Name.IndexOf(channelName, 0, StringComparison.InvariantCultureIgnoreCase) == -1) { continue; } } if (!String.IsNullOrWhiteSpace(gameTitle)) { // Check if the game title has the current filter string. if (c.GameTitle.IndexOf(gameTitle, 0, StringComparison.InvariantCultureIgnoreCase) == -1) { continue; } } if (gameId.HasValue) { if (c.TypeId != gameId) { continue; } } if (fromTime.HasValue) { // Check if this is in the time range we want. if (c.UploadDate < fromTime.Value) { continue; } } if (toTime.HasValue) { // Check if this is in the time range we want. if (c.UploadDate > toTime.Value) { continue; } } if (ViewCountMin.HasValue) { if (c.ViewCount < ViewCountMin) { continue; } } if (partnered.HasValue) { if (partnered.Value != c.Channel.Partnered) { continue; } } if (currentlyLive.HasValue) { if (currentlyLive.Value != c.Channel.Online) { continue; } } if (hypeZoneChannelId.HasValue) { if (hypeZoneChannelId.Value != c.HypeZoneChannelId) { continue; } } if (!String.IsNullOrWhiteSpace(languageFilter)) { if (!c.Channel.Language.Equals(languageFilter, StringComparison.OrdinalIgnoreCase)) { continue; } } // If we got to then end this didn't get filtered. // So add it. output.Add(c); } } return(output); }