/// <summary> /// Returns the highest rank achieved for a level and a given list of difficulties. /// </summary> /// <param name="levelID">The level ID of the level to search through.</param> /// <param name="difficulties">A list of BeatmapDifficulties to search through. Use null to search through all difficulties.</param> /// <param name="characteristics">A list of characteristics to search through. Each characteristic is represented by its serialized string. /// Use null to search through all characteristics.</param> /// <returns>The highest RankModel.Rank enum found for the selected difficulties, or null if the level has not yet been completed.</returns> public RankModel.Rank?GetHighestRankForLevel(string levelID, IEnumerable <BeatmapDifficulty> difficulties = null, IEnumerable <string> characteristics = null) { levelID = BeatmapDetailsLoader.GetSimplifiedLevelID(levelID); if (difficulties == null) { difficulties = LocalLeaderboardDataHelper.AllDifficulties; } if (characteristics == null) { characteristics = AllCharacteristicStrings; } var validEntries = _playerData.levelsStatsData.Where(x => x.levelID.StartsWith(levelID) && x.highScore != 0 && difficulties.Contains(x.difficulty) && characteristics.Contains(x.beatmapCharacteristic.serializedName)); if (validEntries.Count() > 0) { return(validEntries.Max(x => x.maxRank)); } else { return(null); } }
private static string GetCustomLevelHash(string levelID) { var simplifiedID = BeatmapDetailsLoader.GetSimplifiedLevelID(levelID); if (simplifiedID.StartsWith(CustomLevelLoader.kCustomLevelPrefixId)) { return(simplifiedID.Substring(CustomLevelLoader.kCustomLevelPrefixId.Length)); } else { return(simplifiedID); } }
/// <summary> /// Check whether the level has been full combo'd in party mode. /// All duplicate custom beatmaps are treated as full combo'd if any of the duplicates have been full combo'd at least once. /// </summary> /// <param name="levelID">The level ID of the beatmap.</param> /// <param name="difficulties">A list of difficulties to check for a full combo (optional).</param> /// <param name="playerName">The name of the player on the local leaderboards (optional).</param> /// <returns>True if the player(s) has/have achieved a full combo on the beatmap, otherwise false</returns> public bool HasFullComboForLevel(string levelID, IEnumerable <BeatmapDifficulty> difficulties = null, string playerName = null) { levelID = BeatmapDetailsLoader.GetSimplifiedLevelID(levelID); if (difficulties == null || difficulties.Count() == 0) { difficulties = AllDifficulties; } // get any level duplicates List <string> duplicateLevelIDs = GetActualLevelIDs(levelID); StringBuilder sb = new StringBuilder(); foreach (var levID in duplicateLevelIDs) { foreach (var characteristic in AllCharacteristicStrings) { foreach (var difficulty in difficulties) { sb.Clear(); sb.Append(levID); sb.Append(characteristic); sb.Append(difficulty.ToString()); string leaderboardID = sb.ToString(); var scores = _localLeaderboardsModel.GetScores(leaderboardID, LocalLeaderboardsModel.LeaderboardType.AllTime); if (scores != null) { if (scores.Any(x => x._fullCombo && (x._playerName == playerName || playerName == null))) { return(true); } } } } } return(false); }
/// <summary> /// Check whether the player has achieved a full combo for a level on any characteristic and difficulty. /// Optionally, you can limit the search for a full combo to a specific characteristic and/or difficulties. /// All duplicate custom beatmaps are treated as full combo'd if any of the duplicates have been full combo'd at least once. /// </summary> /// <param name="levelID">The level ID of the beatmap.</param> /// <param name="characteristicName">The serialized name of the characteristic to check for a full combo (optional).</param> /// <param name="difficulties">A list of difficulties to check for a full combo (optional).</param> /// <returns>True if the player has achieved a full combo on the beatmap, otherwise false.</returns> public bool HasFullComboForLevel(string levelID, string characteristicName = null, List <BeatmapDifficulty> difficulties = null) { levelID = BeatmapDetailsLoader.GetSimplifiedLevelID(levelID); if (difficulties != null && difficulties.Count == 0) { difficulties = null; } if (!string.IsNullOrEmpty(characteristicName) && difficulties != null) { return(_playerData.levelsStatsData.Any(x => x.levelID.StartsWith(levelID) && x.beatmapCharacteristic.serializedName == characteristicName && difficulties.Contains(x.difficulty) && x.validScore && x.fullCombo && x.maxCombo != 0)); } else if (!string.IsNullOrEmpty(characteristicName)) { return(_playerData.levelsStatsData.Any(x => x.levelID.StartsWith(levelID) && x.beatmapCharacteristic.serializedName == characteristicName && x.validScore && x.fullCombo && x.maxCombo != 0)); } else if (difficulties != null) { return(_playerData.levelsStatsData.Any(x => x.levelID.StartsWith(levelID) && difficulties.Contains(x.difficulty) && x.validScore && x.fullCombo && x.maxCombo != 0)); } else { return(_playerData.levelsStatsData.Any(x => x.levelID.StartsWith(levelID) && x.validScore && x.fullCombo && x.maxCombo != 0)); } }
/// <summary> /// Returns the number of times the player has played a beatmap. /// </summary> /// <param name="levelID">The level ID of the beatmap to check.</param> /// <returns>An integer representing the number of times the player has played the beatmap.</returns> public int GetPlayCountForLevel(string levelID) { levelID = BeatmapDetailsLoader.GetSimplifiedLevelID(levelID); return(_playerData.levelsStatsData.Where(x => x.levelID.StartsWith(levelID)).Sum(x => x.playCount)); }
// beatmaps have to be loaded after everything is created, since only then will the loading view exist private void LoadBeatmaps() { IPreviewBeatmapLevel[] levelsToLoad; if (PluginConfig.ShowFirstTimeLoadingText) { // first time loading should load all custom levels for cache var allCustomLevels = SongCore.Loader.CustomLevels.Values.Select(x => x as IPreviewBeatmapLevel).ToList(); allCustomLevels.AddRange(_unfilteredLevels); levelsToLoad = allCustomLevels.Distinct().ToArray(); } else { levelsToLoad = _unfilteredLevels; } _filterMainViewController.ShowLoadingView(); BeatmapDetailsLoader.instance.StartLoading(levelsToLoad, delegate(int loaded) { // on update, show updated progress text _filterMainViewController.UpdateLoadingProgressText(loaded, levelsToLoad.Length); }, delegate(BeatmapDetails[] levels) { // on finish _filterSideViewController.FilterListActive = true; _filterSideViewController.QuickFilterSectionActive = true; // NOTE: this quick filter check is done here, since the text size calculation cannot be done during DidActivate // it also can't happen before FilterListActive is set to true, otherwise the first time this text is shown, // it will be a tenth of the size of what it should be _filterSideViewController.CheckSelectedQuickFilter(); if (_currentFilter != null) { FilterSelected(_currentFilter); _filterSideViewController.SelectFilterCell(FilterList.ActiveFilters.IndexOf(_currentFilter)); } else { FilterSelected(FilterList.ActiveFilters.First()); _filterSideViewController.SelectFilterCell(0); } RefreshUI(); _beatmapDetails = new Dictionary <IPreviewBeatmapLevel, BeatmapDetails>(_unfilteredLevels.Length); foreach (var level in _unfilteredLevels) { // if a custom level's level ID contains the name of its folder, strip it out var details = levels.FirstOrDefault(x => x?.LevelID == BeatmapDetailsLoader.GetSimplifiedLevelID(level)); if (details == null) { continue; } _beatmapDetails[level] = details; } PluginConfig.ShowFirstTimeLoadingText = false; }); }