public void Initialize(ProgressNotification progressNotification = null) { Server.Log(LogCategory.Notice, "Generating world around spawn point..."); for (int x = -5; x < 5; x++) { for (int z = -5; z < 5; z++) World.GetChunk(new Coordinates2D(x, z)); int progress = (int)(((x + 5) / 10.0) * 100); if (progressNotification != null) progressNotification(progress / 100.0, "Generating world..."); if (progress % 10 == 0) Server.Log(LogCategory.Notice, "{0}% complete", progress + 10); } Server.Log(LogCategory.Notice, "Simulating the world for a moment..."); for (int x = -5; x < 5; x++) { for (int z = -5; z < 5; z++) { var chunk = World.GetChunk(new Coordinates2D(x, z)); for (byte _x = 0; _x < Chunk.Width; _x++) { for (byte _z = 0; _z < Chunk.Depth; _z++) { for (int _y = 0; _y < chunk.GetHeight(_x, _z); _y++) { var coords = new Coordinates3D(x + _x, _y, z + _z); var data = World.GetBlockData(coords); var provider = World.BlockRepository.GetBlockProvider(data.ID); provider.BlockUpdate(data, data, Server, World); } } } } int progress = (int)(((x + 5) / 10.0) * 100); if (progressNotification != null) progressNotification(progress / 100.0, "Simulating world..."); if (progress % 10 == 0) Server.Log(LogCategory.Notice, "{0}% complete", progress + 10); } World.Save(); }
protected abstract void FinalizeSearch(Series series, dynamic options, Boolean reportsFound, ProgressNotification notification);
public abstract List <EpisodeParseResult> PerformSearch(Series series, dynamic options, ProgressNotification notification);
public void Setup() { _notification = new ProgressNotification("Test"); WithTempAsAppPath(); }
public virtual void Start(ProgressNotification notification, dynamic options) { Logger.Info("Running search history cleanup."); _searchHistoryProvider.Cleanup(); }
public Task <IEnumerable <ILive <BeatmapSetInfo> > > Import(ProgressNotification notification, params ImportTask[] tasks) { return(beatmapModelManager.Import(notification, tasks)); }
private void load(BeatmapModelDownloader beatmaps) { this.beatmaps = beatmaps; beatmaps.PostNotification = n => recentNotification = n as ProgressNotification; }
private List <BeatmapCollection> readCollections(Stream stream, ProgressNotification notification = null) { if (notification != null) { notification.Text = "Reading collections..."; notification.Progress = 0; } var result = new List <BeatmapCollection>(); try { using (var sr = new SerializationReader(stream)) { sr.ReadInt32(); // Version int collectionCount = sr.ReadInt32(); result.Capacity = collectionCount; for (int i = 0; i < collectionCount; i++) { if (notification?.CancellationToken.IsCancellationRequested == true) { return(result); } var collection = new BeatmapCollection { Name = { Value = sr.ReadString() } }; int mapCount = sr.ReadInt32(); for (int j = 0; j < mapCount; j++) { if (notification?.CancellationToken.IsCancellationRequested == true) { return(result); } string checksum = sr.ReadString(); var beatmap = beatmaps.QueryBeatmap(b => b.MD5Hash == checksum); if (beatmap != null) { collection.Beatmaps.Add(beatmap); } } if (notification != null) { notification.Text = $"Imported {i + 1} of {collectionCount} collections"; notification.Progress = (float)(i + 1) / collectionCount; } result.Add(collection); } } } catch (Exception e) { Logger.Error(e, "Failed to read collection database."); } return(result); }
public Task <IEnumerable <ScoreInfo> > Import(ProgressNotification notification, params ImportTask[] tasks) { return(scoreModelManager.Import(notification, tasks)); }
/// <summary> /// Downloads a beatmap. /// </summary> /// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param> /// <param name="noVideo">Whether the beatmap should be downloaded without video. Defaults to false.</param> public void Download(BeatmapSetInfo beatmapSetInfo, bool noVideo = false) { var existing = GetExistingDownload(beatmapSetInfo); if (existing != null || api == null) { return; } if (!api.LocalUser.Value.IsSupporter) { PostNotification?.Invoke(new SimpleNotification { Icon = FontAwesome.fa_superpowers, Text = "You gotta be a supporter to download for now 'yo" }); return; } var downloadNotification = new ProgressNotification { CompletionText = $"Imported {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}!", Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo, noVideo); request.DownloadProgressed += progress => { downloadNotification.State = ProgressNotificationState.Active; downloadNotification.Progress = progress; }; request.Success += data => { downloadNotification.Text = $"Importing {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}"; Task.Factory.StartNew(() => { // This gets scheduled back to the update thread, but we want the import to run in the background. using (var stream = new MemoryStream(data)) using (var archive = new OszArchiveReader(stream)) Import(archive); downloadNotification.State = ProgressNotificationState.Completed; }, TaskCreationOptions.LongRunning); currentDownloads.Remove(request); }; request.Failure += data => { downloadNotification.State = ProgressNotificationState.Completed; Logger.Error(data, "Failed to get beatmap download information"); currentDownloads.Remove(request); }; downloadNotification.CancelRequested += () => { request.Cancel(); currentDownloads.Remove(request); downloadNotification.State = ProgressNotificationState.Cancelled; return(true); }; currentDownloads.Add(request); PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. Task.Factory.StartNew(() => request.Perform(api), TaskCreationOptions.LongRunning); BeatmapDownloadBegan?.Invoke(request); }
protected override void FinalizeSearch(Series series, dynamic options, Boolean reportsFound, ProgressNotification notification) { logger.Warn("Unable to find {0} in any of indexers.", options.Episode); notification.CurrentMessage = reportsFound ? String.Format("Sorry, couldn't find {0}, that matches your preferences.", options.Episode.AirDate) : String.Format("Sorry, couldn't find {0} in any of indexers.", options.Episode); }
public override List <EpisodeParseResult> PerformSearch(Series series, dynamic options, ProgressNotification notification) { if (options.Episode == null) { throw new ArgumentException("Episode is invalid"); } notification.CurrentMessage = "Looking for " + options.Episode; var reports = new List <EpisodeParseResult>(); var title = GetSearchTitle(series); Parallel.ForEach(_indexerProvider.GetEnabledIndexers(), indexer => { try { reports.AddRange(indexer.FetchDailyEpisode(title, options.Episode.AirDate)); } catch (Exception e) { logger.ErrorException(String.Format("An error has occurred while searching for {0} - {1:yyyy-MM-dd} from: {2}", series.Title, options.Episode.AirDate, indexer.Name), e); } }); return(reports); }
protected void Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; notification.Text = "Import is initialising..."; var term = $"{typeof(TModel).Name.Replace("Info", "").ToLower()}"; List <TModel> imported = new List <TModel>(); int current = 0; foreach (string path in paths) { if (notification.State == ProgressNotificationState.Cancelled) { // user requested abort return; } try { var text = "Importing "; if (path.Length > 1) { text += $"{++current} of {paths.Length} {term}s.."; } else { text += $"{term}.."; } // only show the filename if it isn't a temporary one (as those look ugly). if (!path.Contains(Path.GetTempPath())) { text += $"\n{Path.GetFileName(path)}"; } notification.Text = text; imported.Add(Import(path)); notification.Progress = (float)current / paths.Length; } catch (Exception e) { e = e.InnerException ?? e; Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); } } if (imported.Count == 0) { notification.Text = "Import failed!"; notification.State = ProgressNotificationState.Cancelled; } else { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" : $"Imported {current} {term}s!"; if (imported.Count > 0 && PresentImport != null) { notification.CompletionText += " Click to view."; notification.CompletionClickAction = () => { PresentImport?.Invoke(imported); return(true); }; } notification.State = ProgressNotificationState.Completed; } }
public void Register(ProgressNotification notification) { _progressNotification.Add(notification.Id, notification); }
public virtual SearchHistory ProcessReports(Series series, dynamic options, List <EpisodeParseResult> episodeParseResults, SearchHistory searchResult, ProgressNotification notification) { var items = new List <SearchHistoryItem>(); searchResult.Successes = new List <Int32>(); foreach (var episodeParseResult in episodeParseResults .OrderByDescending(c => c.Quality) .ThenBy(c => c.EpisodeNumbers.MinOrDefault()) .ThenBy(c => c.Age)) { try { var item = new SearchHistoryItem { ReportTitle = episodeParseResult.OriginalString, NzbUrl = episodeParseResult.NzbUrl, Indexer = episodeParseResult.Indexer, Quality = episodeParseResult.Quality.Quality, Proper = episodeParseResult.Quality.Proper, Size = episodeParseResult.Size, Age = episodeParseResult.Age, Language = episodeParseResult.Language }; items.Add(item); logger.Trace("Analysing report " + episodeParseResult); episodeParseResult.Series = _seriesProvider.FindSeries(episodeParseResult.CleanTitle); if (episodeParseResult.Series == null || episodeParseResult.Series.SeriesId != series.SeriesId) { item.SearchError = ReportRejectionType.WrongSeries; continue; } episodeParseResult.Episodes = _episodeProvider.GetEpisodesByParseResult(episodeParseResult); if (searchResult.Successes.Intersect(episodeParseResult.Episodes.Select(e => e.EpisodeId)).Any()) { item.SearchError = ReportRejectionType.Skipped; continue; } CheckReport(series, options, episodeParseResult, item); if (item.SearchError != ReportRejectionType.None) { continue; } item.SearchError = _allowedDownloadSpecification.IsSatisfiedBy(episodeParseResult); if (item.SearchError == ReportRejectionType.None) { if (DownloadReport(notification, episodeParseResult, item)) { searchResult.Successes.AddRange(episodeParseResult.Episodes.Select(e => e.EpisodeId)); } } } catch (Exception e) { logger.ErrorException("An error has occurred while processing parse result items from " + episodeParseResult, e); } } searchResult.SearchHistoryItems = items; return(searchResult); }
protected async Task <IEnumerable <TModel> > Import(ProgressNotification notification, params ImportTask[] tasks) { if (tasks.Length == 0) { notification.CompletionText = $"No {HumanisedModelName}s were found to import!"; notification.State = ProgressNotificationState.Completed; return(Enumerable.Empty <TModel>()); } notification.Progress = 0; notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import is initialising..."; int current = 0; var imported = new List <TModel>(); bool isLowPriorityImport = tasks.Length > low_priority_import_batch_size; await Task.WhenAll(tasks.Select(async task => { notification.CancellationToken.ThrowIfCancellationRequested(); try { var model = await Import(task, isLowPriorityImport, notification.CancellationToken); lock (imported) { if (model != null) { imported.Add(model); } current++; notification.Text = $"Imported {current} of {tasks.Length} {HumanisedModelName}s"; notification.Progress = (float)current / tasks.Length; } } catch (TaskCanceledException) { throw; } catch (Exception e) { Logger.Error(e, $@"Could not import ({task})", LoggingTarget.Database); } })); if (imported.Count == 0) { notification.Text = $"{HumanisedModelName.Humanize(LetterCasing.Title)} import failed!"; notification.State = ProgressNotificationState.Cancelled; } else { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" : $"Imported {imported.Count} {HumanisedModelName}s!"; if (imported.Count > 0 && PresentImport != null) { notification.CompletionText += " Click to view."; notification.CompletionClickAction = () => { PresentImport?.Invoke(imported); return(true); }; } notification.State = ProgressNotificationState.Completed; } return(imported); }
/// <summary> /// Import one or more <see cref="TModel"/> items from filesystem <paramref name="paths"/>. /// This will post notifications tracking progress. /// </summary> /// <param name="paths">One or more archive locations on disk.</param> public void Import(params string[] paths) { var notification = new ProgressNotification { Text = "Import is initialising...", Progress = 0, State = ProgressNotificationState.Active, }; PostNotification?.Invoke(notification); List <TModel> imported = new List <TModel>(); int current = 0; foreach (string path in paths) { if (notification.State == ProgressNotificationState.Cancelled) { // user requested abort return; } try { notification.Text = $"Importing ({++current} of {paths.Length})\n{Path.GetFileName(path)}"; TModel import; using (ArchiveReader reader = getReaderFrom(path)) imported.Add(import = Import(reader)); notification.Progress = (float)current / paths.Length; // We may or may not want to delete the file depending on where it is stored. // e.g. reconstructing/repairing database with items from default storage. // Also, not always a single file, i.e. for LegacyFilesystemReader // TODO: Add a check to prevent files from storage to be deleted. try { if (import != null && File.Exists(path)) { File.Delete(path); } } catch (Exception e) { Logger.Error(e, $@"Could not delete original file after import ({Path.GetFileName(path)})"); } } catch (Exception e) { e = e.InnerException ?? e; Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})"); } } if (imported.Count == 0) { notification.Text = "Import failed!"; notification.State = ProgressNotificationState.Cancelled; } else { notification.CompletionText = $"Imported {current} {typeof(TModel).Name.Replace("Info", "").ToLower()}s!"; notification.CompletionClickAction += () => { if (imported.Count > 0) { PresentCompletedImport(imported); } return(true); }; notification.State = ProgressNotificationState.Completed; } }
public void Start(ProgressNotification notification, dynamic options) { List <Series> seriesToRename; if (options == null || options.SeriesId <= 0) { seriesToRename = _seriesProvider.GetAllSeries().ToList(); } else { seriesToRename = new List <Series> { _seriesProvider.GetSeries(options.SeriesId) }; } foreach (var series in seriesToRename) { notification.CurrentMessage = String.Format("Renaming episodes for '{0}'", series.Title); Logger.Debug("Getting episodes from database for series: {0}", series.SeriesId); var episodeFiles = _mediaFileProvider.GetSeriesFiles(series.SeriesId); if (episodeFiles == null || episodeFiles.Count == 0) { Logger.Warn("No episodes in database found for series: {0}", series.SeriesId); return; } var newEpisodeFiles = new List <EpisodeFile>(); var oldEpisodeFiles = new List <EpisodeFile>(); foreach (var episodeFile in episodeFiles) { try { var oldFile = new EpisodeFile(episodeFile); var newFile = _diskScanProvider.MoveEpisodeFile(episodeFile); if (newFile != null) { newEpisodeFiles.Add(newFile); oldEpisodeFiles.Add(oldFile); } } catch (Exception e) { Logger.WarnException("An error has occurred while renaming file", e); } } //Remove & Create Metadata for episode files _metadataProvider.RemoveForEpisodeFiles(oldEpisodeFiles); _metadataProvider.CreateForEpisodeFiles(newEpisodeFiles); //Start AfterRename var message = String.Format("Renamed: Series {0}", series.Title); _externalNotificationProvider.AfterRename(message, series); notification.CurrentMessage = String.Format("Rename completed for {0}", series.Title); } }
protected async Task Import(ProgressNotification notification, params string[] paths) { notification.Progress = 0; notification.Text = "Import is initialising..."; int current = 0; var imported = new List <TModel>(); await Task.WhenAll(paths.Select(async path => { notification.CancellationToken.ThrowIfCancellationRequested(); try { var model = await Import(path, notification.CancellationToken); lock (imported) { if (model != null) { imported.Add(model); } current++; notification.Text = $"Imported {current} of {paths.Length} {HumanisedModelName}s"; notification.Progress = (float)current / paths.Length; } } catch (TaskCanceledException) { throw; } catch (Exception e) { Logger.Error(e, $@"Could not import ({Path.GetFileName(path)})", LoggingTarget.Database); } })); if (imported.Count == 0) { notification.Text = "Import failed!"; notification.State = ProgressNotificationState.Cancelled; } else { notification.CompletionText = imported.Count == 1 ? $"Imported {imported.First()}!" : $"Imported {imported.Count} {HumanisedModelName}s!"; if (imported.Count > 0 && PresentImport != null) { notification.CompletionText += " Click to view."; notification.CompletionClickAction = () => { PresentImport?.Invoke(imported); return(true); }; } notification.State = ProgressNotificationState.Completed; } }
/// <summary> /// Downloads a beatmap. /// </summary> /// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param> /// <returns>A new <see cref="DownloadBeatmapSetRequest"/>, or an existing one if a download is already in progress.</returns> public DownloadBeatmapSetRequest Download(BeatmapSetInfo beatmapSetInfo) { var existing = GetExistingDownload(beatmapSetInfo); if (existing != null) { return(existing); } if (api == null) { return(null); } ProgressNotification downloadNotification = new ProgressNotification { Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}", }; var request = new DownloadBeatmapSetRequest(beatmapSetInfo); request.DownloadProgressed += progress => { downloadNotification.State = ProgressNotificationState.Active; downloadNotification.Progress = progress; }; request.Success += data => { downloadNotification.State = ProgressNotificationState.Completed; using (var stream = new MemoryStream(data)) using (var archive = new OszArchiveReader(stream)) Import(archive); currentDownloads.Remove(request); }; request.Failure += data => { downloadNotification.State = ProgressNotificationState.Completed; Logger.Error(data, "Failed to get beatmap download information"); currentDownloads.Remove(request); }; downloadNotification.CancelRequested += () => { request.Cancel(); currentDownloads.Remove(request); downloadNotification.State = ProgressNotificationState.Cancelled; return(true); }; currentDownloads.Add(request); PostNotification?.Invoke(downloadNotification); // don't run in the main api queue as this is a long-running task. Task.Run(() => request.Perform(api)); return(request); }
public virtual void Start(ProgressNotification notification, dynamic options) { _logProvider.Trim(); }