/// <inheritdoc /> public IReadOnlyList <BasicInfo> GetResponse(IReadOnlyList <string> entities, bool outputResults) { TmdbServiceConfiguration.SetServiceConfigurationOnce( GetServiceConfiguration(outputResults) ); // Use HashSet to avoid duplicated data which can produce errors in further work. var searchResults = new HashSet <BasicInfo>(); foreach (string movie in entities) { TmdbSearchContainer?response = _tmdbClient.TrySearchMovieAsync(movie).Result; if (response is null || response.Results.IsNullOrEmpty()) { string message = $"{movie} was not processed."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); continue; } // Get first search result from response and ignore all the rest. TmdbMovieInfo searchResult = response.Results.First(); if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {searchResult.Title} from \"{Tag}\"."); } searchResults.Add(searchResult); } return(searchResults.ToList()); }
public override async Task <bool> GetRatings(BufferBlock <BasicInfo> entitiesInfoQueue, BufferBlock <RatingDataContainer> entitiesRatingQueue, bool outputResults) { while (await entitiesInfoQueue.OutputAvailableAsync()) { BasicInfo entityInfo = await entitiesInfoQueue.ReceiveAsync(); var movieTmdbInfo = (TmdbMovieInfo)entityInfo; double rating = _fuzzyController.CalculateRating( movieTmdbInfo.VoteCount, movieTmdbInfo.VoteAverage, movieTmdbInfo.ReleaseDate.Year, movieTmdbInfo.Popularity, movieTmdbInfo.Adult ? 1 : 0 ); var resultInfo = new RatingDataContainer(entityInfo, rating); await entitiesRatingQueue.SendAsync(resultInfo); if (outputResults) { GlobalMessageHandler.OutputMessage($"Appraised {resultInfo} by {Tag}"); } } return(true); }
/// <inheritdoc /> public IReadOnlyList <BasicInfo> GetResponse(IReadOnlyList <string> entities, bool outputResults) { // Use HashSet to avoid duplicated data which can produce errors in further work. var searchResults = new HashSet <BasicInfo>(); foreach (string movie in entities) { OmdbMovieInfo?response = _omdbClient.TryGetItemByTitleAsync(movie).Result; if (response is null) { string message = $"{movie} was not processed."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); continue; } // Get first search result from response and ignore all the rest. if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {response.Title} from \"{Tag}\"."); } searchResults.Add(response); } return(searchResults.ToList()); }
/// <summary> /// Gets extension from MIME type. /// </summary> /// <param name="mimeType">MIME type to process.</param> /// <returns>Appropriate extension to passed type.</returns> protected static string GetExtension(string mimeType) { switch (mimeType) { case "text/plain": return(".txt"); case "text/csv": return(".csv"); case "text/html": return(".html"); case "application/rtf": return(".rtf"); case "application/pdf": return(".pdf"); default: _logger.Warn($"Not found extension for MIME type: {mimeType}"); GlobalMessageHandler.OutputMessage( $"Not found extension for MIME type: {mimeType}" ); return(string.Empty); } }
public async Task GlobalMessageHandler_should_wrap_HttpError_in_WrappedApiError() { var handler = new GlobalMessageHandler(); var message = "foo"; var messageDetail = "bar"; handler.InnerHandler = new HttpErrorResponder(message, messageDetail); var request = new HttpRequestMessage(); var response = await handler.SendAsyncTestHook(request, new CancellationToken()); var result = await response.Content.ReadAsAsync <WrappedApiError <ApiError> >(); Assert.IsNotNull(result.Error); // Outer error should have correct code string and message Assert.AreEqual(response.StatusCode.ToString(), result.Error.Code); Assert.AreEqual(message, result.Error.Message); // Details should have correct code string and message detail Assert.AreEqual(1, result.Error.Details?.Length); Assert.AreEqual(response.StatusCode.ToString(), result.Error.Details?[0]?.Code); Assert.AreEqual(messageDetail, result.Error.Details?[0]?.Message); }
/// <summary> /// Method with logic of execution the Console Application which created shell to process /// data. /// </summary> /// <param name="args">Represents the command-line arguments.</param> /// <param name="shell">Represents the main manager of the library.</param> private static async Task Run(IReadOnlyList <string> args, ShellAsync shell) { ServiceStatus status; if (args.Count == 1) { status = await shell.Run(args[0]); } else { GlobalMessageHandler.OutputMessage( "Enter filename which contains the Things: " ); status = await shell.Run(GlobalMessageHandler.GetMessage()); } if (status == ServiceStatus.Nothing) { GlobalMessageHandler.OutputMessage("Result is empty. Closing..."); } else { GlobalMessageHandler.OutputMessage("Work was finished! Press enter to exit..."); } GlobalMessageHandler.GetMessage(); }
/// <inheritdoc /> public async IAsyncEnumerable <BasicInfo> GetResponse(string entityName, bool outputResults) { OmdbMovieInfo?response = await _omdbClient.TryGetItemByTitleAsync(entityName); if (response is null) { string message = $"{entityName} was not processed."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); yield break; } // Get first search result from response and ignore all the rest. if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {response.Title} from \"{Tag}\"."); } if (_searchResults.Add(response)) { yield return(response); } yield break; }
/// <summary> /// Makes prior analysis through normalizers and calculates ratings based on average vote /// and vote count. /// </summary> /// <param name="rawDataContainer">Entities to appraise with additional parameters.</param> /// <param name="outputResults">Flag to define need to output.</param> /// <returns>Collection of result object (data object with rating).</returns> /// <remarks> /// Entities collection must be unique because rating calculation errors can occur in such /// situations. /// </remarks> public virtual ResultList GetRatings(RawDataContainer rawDataContainer, bool outputResults) { CheckRatingId(); var ratings = new ResultList(); IReadOnlyList <BasicInfo> rawData = rawDataContainer.GetData(); if (rawData.IsNullOrEmpty()) { return(ratings); } MinMaxDenominator voteCountMMD = rawDataContainer.GetParameter("VoteCount"); MinMaxDenominator voteAverageMMD = rawDataContainer.GetParameter("VoteAverage"); foreach (BasicInfo entityInfo in rawData) { double ratingValue = CalculateRating(entityInfo, voteCountMMD, voteAverageMMD); var resultInfo = new ResultInfo(entityInfo.ThingId, ratingValue, RatingId); ratings.Add(resultInfo); if (outputResults) { GlobalMessageHandler.OutputMessage(resultInfo.ToString()); } } ratings.Sort((x, y) => y.RatingValue.CompareTo(x.RatingValue)); return(ratings); }
/// <summary> /// Sends request and collect data from all services. /// </summary> /// <param name="names">Collection of The Things names which need to appraise.</param> private void RequestData(List <string> names) { try { IReadOnlyList <IReadOnlyList <BasicInfo> > results = CrawlersManager.CollectAllResponses(names); if (results.Count == 0) { GlobalMessageHandler.OutputMessage( "Crawlers have not received responses from services. Result is empty." ); _status = ServiceStatus.Nothing; } else { DataBaseManager.DeleteData(); DataBaseManager.PutResultsToDb(results); GlobalMessageHandler.OutputMessage( "Crawlers have received responses from services." ); _status = ServiceStatus.Ok; } } catch (Exception ex) { _logger.Error(ex, "Exception occured during collecting data."); _status = ServiceStatus.RequestError; } }
/// <summary> /// Finds suitable appraisers for every collection and execute ratings calculations. /// </summary> /// <param name="data">Collections of crawlers results.</param> /// <returns>Appraised collections produced from a set of data.</returns> public ProcessedDataContainer GetAllRatings(List <RawDataContainer> data) { var results = new List <ResultList>(); foreach (RawDataContainer datum in data) { IReadOnlyList <BasicInfo> internalData = datum.GetData(); // Skip empty collections of data. if (internalData.IsNullOrEmpty()) { continue; } // Suggest that all types in collection are identical. if (!_appraisers.TryGetValue(internalData[0].GetType(), out List <Appraiser> values)) { string message = $"Type {internalData[0].GetType()} wasn't used to appraise!"; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); continue; } foreach (Appraiser appraiser in values) { results.Add(appraiser.GetRatings(datum, _outputResults)); } } return(new ProcessedDataContainer(results, _ratingsStorage)); }
public void PutResultsToDb(IReadOnlyList <IReadOnlyList <BasicInfo> > results) { foreach (IReadOnlyList <BasicInfo> datum in results) { // Skip empty collections of data. if (datum.IsNullOrEmpty()) { continue; } // Suggest that all types in collection are identical. if (!_repositories.TryGetValue(datum[0].GetType(), out IDataRepository repository)) { _logger.Info($"Type {datum[0].GetType()} didn't save!"); GlobalMessageHandler.OutputMessage( $"Type {datum[0].GetType()} didn't save!" ); continue; } foreach (BasicInfo info in datum) { if (repository.Contains(info.ThingId)) { repository.UpdateItem(info); } else { repository.InsertItem(info); } } } }
public async Task <bool> GetNames(BufferBlock <string> queueToWrite, string storageName) { if (string.IsNullOrWhiteSpace(storageName)) { storageName = _defaultStorageName; string message = "Storage name is empty, using the default value."; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); } List <Task <bool> > producers = _inputtersAsync.Select( inputterAsync => TryReadThingNames(inputterAsync, queueToWrite, storageName) ).ToList(); bool[] statuses = await Task.WhenAll(producers); queueToWrite.Complete(); if (!statuses.IsNullOrEmpty() && statuses.All(r => r)) { _logger.Info($"{statuses.Length} Thing names queues were read."); return(true); } _logger.Info($"No Things were found in \"{storageName}\"."); return(false); }
/// <summary> /// Reads Thing names from input source. /// </summary> /// <param name="storageName">Name of the input source.</param> /// <returns>Collection of The Thing names as strings.</returns> private List <string> GetThingNames(string storageName) { var names = new List <string>(); try { names = InputManager.GetNames(storageName); if (names.Count == 0) { GlobalMessageHandler.OutputMessage( $"No Things were found in \"{storageName}\"." ); _status = ServiceStatus.Nothing; } else { GlobalMessageHandler.OutputMessage("Things were successfully gotten."); _status = ServiceStatus.Ok; } } catch (Exception ex) { _logger.Error(ex, "Exception occured during input work."); _status = ServiceStatus.InputError; } return(names); }
/// <summary> /// Get names from inputter with specified storage name. /// </summary> /// <param name="storageName">Input storage name.</param> /// <returns>Collection of The Things names as strings.</returns> public List <string> GetNames(string storageName) { var result = new List <string>(); if (string.IsNullOrWhiteSpace(storageName)) { storageName = _defaultStorageName; string message = "Storage name is empty, using the default value."; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); } foreach (IInputter inputter in _inputters) { bool success = TryReadThingNames(inputter, storageName, out IReadOnlyList <string> value); if (!success || value.IsNullOrEmpty()) { string message = $"No Things were found in {storageName} by inputter " + $"{inputter.Tag}."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); continue; } result.AddRange(value); } _logger.Info($"{result.Count} Things were found."); return(result); }
private async Task <ServiceStatus> RequestData(BufferBlock <string> entitiesQueue, IDictionary <Type, BufferBlock <BasicInfo> > rawDataQueues) { try { bool status = await CrawlersManagerAsync.CollectAllResponses( entitiesQueue, rawDataQueues, _dataFlowOptions ); if (status) { GlobalMessageHandler.OutputMessage( "Crawlers have received responses from services." ); return(ServiceStatus.Ok); } GlobalMessageHandler.OutputMessage( "Crawlers have not received responses from services. Result is empty." ); return(ServiceStatus.Nothing); } catch (Exception ex) { _logger.Error(ex, "Exception occured during collecting data."); return(ServiceStatus.RequestError); } }
/// <summary> /// Executes saving procedure and get it status as boolean variable. /// </summary> /// <param name="results">Collections of appraised results to save.</param> /// <param name="storageName">Storage name of output source.</param> /// <returns><c>true</c> if the save was successful, <c>false</c> otherwise.</returns> public bool SaveResults(IReadOnlyList <IReadOnlyList <RatingDataContainer> > results, string storageName) { if (string.IsNullOrWhiteSpace(storageName)) { storageName = _defaultStorageName; string message = "Storage name is empty, using the default value."; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); } List <bool> statuses = _outputters.Select( outputter => outputter.SaveResults(results, storageName) ).ToList(); if (!statuses.IsNullOrEmpty() && statuses.All(r => r)) { _logger.Info($"Successfully saved all results to \"{storageName}\"."); return(true); } _logger.Info($"Couldn't save some results to \"{storageName}\"."); return(false); }
/// <inheritdoc /> public async IAsyncEnumerable <BasicInfo> GetResponse(string entityName, bool outputResults) { TmdbServiceConfiguration.SetServiceConfigurationOnce( await GetServiceConfiguration(outputResults) ); TmdbSearchContainer?response = await _tmdbClient.TrySearchMovieAsync(entityName); if (response is null || response.Results.IsNullOrEmpty()) { string message = $"{entityName} was not processed."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); yield break; } // Get first search result from response and ignore all the rest. TmdbMovieInfo searchResult = response.Results.First(); if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {searchResult.Title} from \"{Tag}\"."); } if (_searchResults.Add(searchResult)) { yield return(searchResult); } yield break; }
private async Task <ServiceStatus> AppraiseThings( IDictionary <Type, BufferBlock <BasicInfo> > rawDataQueues, IList <BufferBlock <RatingDataContainer> > appraisedDataQueues) { try { bool status = await AppraisersManagerAsync.GetAllRatings( rawDataQueues, appraisedDataQueues, _dataFlowOptions ); if (status) { GlobalMessageHandler.OutputMessage( "Appraisers have calculated ratings successfully." ); return(ServiceStatus.Ok); } GlobalMessageHandler.OutputMessage( "Appraisers have not calculated ratings. Result is empty." ); return(ServiceStatus.Nothing); } catch (Exception ex) { _logger.Error(ex, "Exception occured during appraising work."); return(ServiceStatus.AppraiseError); } }
/// <summary> /// Saves ratings to the output sources. /// </summary> /// <returns><c>true</c> if the save was successful, <c>false</c> otherwise.</returns> private bool SaveResults(RatingsStorage ratingsStorage) { bool success = false; try { var ratings = DataBaseManager.GetRatingValuesFromDb(ratingsStorage); if (OutputManager.SaveResults(ratings, string.Empty)) { success = true; _status = ServiceStatus.Ok; GlobalMessageHandler.OutputMessage("Ratings was saved successfully."); } else { _status = ServiceStatus.OutputUnsaved; GlobalMessageHandler.OutputMessage("Ratings wasn't saved."); } } catch (Exception ex) { _logger.Error(ex, "Exception occured during output work."); _status = ServiceStatus.OutputError; } return(success); }
/// <inheritdoc /> public override List <BasicInfo> GetResponse(List <string> entities, bool outputResults) { if (!TmdbServiceConfiguration.HasValue) { TmdbServiceConfiguration.SetServiceConfigurationIfNeed( GetServiceConfiguration(outputResults) ); } // Use HashSet to avoid duplicated data which can produce errors in further work. var searchResults = new HashSet <BasicInfo>(); foreach (string movie in entities) { SearchContainer <SearchMovie> response = _tmdbClient.SearchMovieAsync(movie).Result; if (response.Results.IsNullOrEmpty()) { _logger.Warn($"{movie} wasn't processed."); GlobalMessageHandler.OutputMessage($"{movie} wasn't processed."); continue; } // Get first search result from response and ignore all the rest. SearchMovie searchResult = response.Results.First(); if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {searchResult.Title} from {Tag}"); } TmdbMovieInfo extractedInfo = _dataMapper.Transform(searchResult); searchResults.Add(extractedInfo); } return(searchResults.ToList()); }
/// <summary> /// Finds suitable appraisers for every collection and execute ratings calculations. /// </summary> /// <param name="data">Collections of crawlers results.</param> /// <returns>Appraised collections produced from a set of data.</returns> /// <exception cref="ArgumentNullException"> /// <paramref name="data" /> is <c>null</c>. /// </exception> public ProcessedDataContainer GetAllRatings(IReadOnlyList <RawDataContainer> data) { data.ThrowIfNull(nameof(data)); var results = new List <IReadOnlyList <ResultInfo> >(); foreach (RawDataContainer datum in data) { IReadOnlyList <BasicInfo> internalData = datum.RawData; // Skip empty collections of data. if (!internalData.Any()) { continue; } // Suggest that all types in collection are identical. Type itemsType = internalData.First().GetType(); if (!_appraisers.TryGetValue(itemsType, out IList <IAppraiser> values)) { string message = $"Type {itemsType} was not used to appraise!"; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); continue; } foreach (IAppraiser appraiser in values) { results.Add(appraiser.GetRatings(datum, _outputResults)); } } return(new ProcessedDataContainer(results, _ratingsStorage)); }
/// <summary> /// Method with logic of execution the Console Application which created shell to process data. /// </summary> /// <param name="args">Represents the command-line arguments.</param> /// <param name="shell">Represents the main manager of the library.</param> private static void Run(string[] args, ShellAsync shell) { ServiceStatus status; if (args.Length == 1) { status = shell.Run(args[0]).Result; } else { GlobalMessageHandler.OutputMessage( "Enter filename which contains the Things: " ); status = shell.Run(GlobalMessageHandler.GetMessage()).Result; } if (status == ServiceStatus.Nothing) { GlobalMessageHandler.OutputMessage("Result is empty. Closing..."); } else { GlobalMessageHandler.OutputMessage("Work was finished! Press enter to exit..."); } GlobalMessageHandler.GetMessage(); }
public async Task <bool> GetAllRatings( IDictionary <Type, BufferBlock <BasicInfo> > rawDataQueues, IList <BufferBlock <RatingDataContainer> > appraisedDataQueues, DataflowBlockOptions options) { var producers = new List <Task <bool> >(rawDataQueues.Count); var consumersTasks = new List <Task>(rawDataQueues.Count); var splitQueueTasks = new List <Task>(rawDataQueues.Count); foreach (KeyValuePair <Type, BufferBlock <BasicInfo> > keyValue in rawDataQueues) { if (!_appraisersAsync.TryGetValue(keyValue.Key, out List <AppraiserAsync> values)) { string message = $"Type {keyValue.Key} wasn't used to appraise!"; _logger.Info(message); GlobalMessageHandler.OutputMessage(message); continue; } var consumers = new List <BufferBlock <BasicInfo> >(values.Count); foreach (AppraiserAsync appraiserAsync in values) { var consumer = new BufferBlock <BasicInfo>(options); var appraisedDataQueue = new BufferBlock <RatingDataContainer>(options); appraisedDataQueues.Add(appraisedDataQueue); producers.Add( appraiserAsync.GetRatings(consumer, appraisedDataQueue, _outputResults) ); consumers.Add(consumer); } consumersTasks.Add(Task.WhenAll(consumers.Select(consumer => consumer.Completion))); splitQueueTasks.Add(SplitQueue(keyValue.Value, consumers)); } Task <bool[]> statusesTask = Task.WhenAll(producers); Task consumersFinalTask = Task.WhenAll(consumersTasks); Task splitQueueFinalTask = Task.WhenAll(splitQueueTasks); await Task.WhenAll(splitQueueFinalTask, consumersFinalTask, statusesTask); bool[] statuses = await statusesTask; foreach (BufferBlock <RatingDataContainer> appraisedQueue in appraisedDataQueues) { appraisedQueue.Complete(); } if (!statuses.IsNullOrEmpty() && statuses.All(r => r)) { _logger.Info("Appraisers have finished work."); return(true); } _logger.Info("Appraisers have not processed any data."); return(false); }
/// <summary> /// Gets service configuration. /// </summary> /// <param name="outputResults">Flag to define need to output.</param> /// <returns>Transformed configuration of the service.</returns> private TmdbServiceConfigurationInfo GetServiceConfiguration(bool outputResults) { TmdbServiceConfigurationInfo config = _tmdbClient.GetConfigAsync().Result; if (outputResults) { GlobalMessageHandler.OutputMessage("Got TMDb config."); } return(config); }
public async Task <ServiceStatus> Run(string storageName) { GlobalMessageHandler.OutputMessage("Shell started work."); _logger.Info("Shell started work."); var inputQueue = new BufferBlock <string>(_dataFlowOptions); var rawDataQueues = new Dictionary <Type, BufferBlock <BasicInfo> >(); var appraisedDataQueues = new List <BufferBlock <RatingDataContainer> >(); // Input component work. Task <ServiceStatus> inputStatus = GetThingNames(inputQueue, storageName); // Crawlers component work. Task <ServiceStatus> crawlersStatus = RequestData(inputQueue, rawDataQueues); // Appraisers component work. Task <ServiceStatus> appraisersStatus = AppraiseThings(rawDataQueues, appraisedDataQueues); // Output component work. Task <ServiceStatus> outputStatus = SaveResults(appraisedDataQueues); Task <ServiceStatus[]> statusesTask = Task.WhenAll(inputStatus, crawlersStatus, appraisersStatus, outputStatus); Task rawDataQueuesTasks = Task.WhenAll( rawDataQueues.Values.Select(bufferBlock => bufferBlock.Completion) ); Task appraisedDataQueuesTasks = Task.WhenAll( appraisedDataQueues.Select(bufferBlock => bufferBlock.Completion) ); await Task.WhenAll(statusesTask, inputQueue.Completion, rawDataQueuesTasks, appraisedDataQueuesTasks); // FIX ME: if there are error statuses need to create aggregate status which contains // more details then simple ServiceStatus.Error value. ServiceStatus[] statuses = await statusesTask; if (statuses.Any(status => status != ServiceStatus.Ok)) { GlobalMessageHandler.OutputMessage( "Shell got error status during data processing." ); _logger.Info("Shell got error status during data processing."); return(ServiceStatus.Error); } _logger.Info("Shell finished work successfully."); GlobalMessageHandler.OutputMessage("Shell finished work successfully."); return(ServiceStatus.Ok); }
public async Task GlobalMessageHandler_should_pass_a_WrappedApiError_unmodified() { var handler = new GlobalMessageHandler(); handler.InnerHandler = new WrappedApiErrorResponder(); var request = new HttpRequestMessage(); var response = await handler.SendAsyncTestHook(request, new CancellationToken()); var result = await response.Content.ReadAsAsync <WrappedApiError <ForbiddenApiError> >(); Assert.IsNotNull(result.Error); Assert.AreEqual(HttpStatusCode.Forbidden.ToString(), result.Error.Code); }
/// <summary> /// Deletes the specified file. /// </summary> /// <param name="filename">Filename to delete.</param> /// <returns><c>true</c> if no exception occured, <c>false</c> otherwise.</returns> protected static bool DeleteFile(string filename) { try { File.Delete(filename); } catch (Exception ex) { _logger.Warn(ex, $"Couldn't delete downloaded file \"{filename}\"."); GlobalMessageHandler.OutputMessage("Couldn't delete downloaded file " + $" \"{filename}\". Error: {ex}"); return(false); } return(true); }
/// <summary> /// Makes prior analysis through prepare stage for strategy and then uses it to calculate /// ratings. /// </summary> /// <param name="rawDataContainer"> /// The entities to appraise with additional parameters. /// </param> /// <param name="outputResults">The flag to define need to output.</param> /// <returns>Collection of result object (data object with rating).</returns> /// <remarks> /// Entities collection must be unique because rating calculation errors can occur in such /// situations. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="rawDataContainer" /> is <c>null</c>. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="rawDataContainer" /> contains instances of invalid type for this /// appraiser. /// </exception> public IReadOnlyList <ResultInfo> GetRatings(RawDataContainer rawDataContainer, bool outputResults) { rawDataContainer.ThrowIfNull(nameof(rawDataContainer)); CheckRatingId(); var ratings = new List <ResultInfo>(); IReadOnlyList <BasicInfo> rawData = rawDataContainer.RawData; if (!rawData.Any()) { return(ratings); } // Check if list have proper type. IReadOnlyList <T> converted = rawData.Select(e => { if (!(e is T result)) { throw new ArgumentException( $"Element \"{e.Title}\" (ID = {e.ThingId.ToString()}) type " + $"\"{e.GetType().FullName}\" is invalid for appraiser with type " + $"\"{TypeId.FullName}\"." ); } return(result); }).ToList(); _appraisal.PrepareCalculation(rawDataContainer); foreach (T entityInfo in converted) { double ratingValue = _appraisal.CalculateRating(entityInfo); var resultInfo = new ResultInfo(entityInfo.ThingId, ratingValue, RatingId); ratings.Add(resultInfo); if (outputResults) { GlobalMessageHandler.OutputMessage($"Appraised {resultInfo} by {Tag}."); } } ratings.Sort((x, y) => y.RatingValue.CompareTo(x.RatingValue)); return(ratings); }
/// <inheritdoc /> public IReadOnlyList <BasicInfo> GetResponse(IReadOnlyList <string> entities, bool outputResults) { if (SteamAppsStorage.IsEmpty) { SteamBriefInfoContainer steamApps = _steamApiClient.GetAppListAsync().Result; SteamAppsStorage.FillStorage(steamApps); } // Use HashSet to avoid duplicated data which can produce errors in further work. var searchResults = new HashSet <BasicInfo>(); foreach (string game in entities) { int?appId = SteamAppsStorage.TryGetAppIdByName(game); if (!appId.HasValue) { string message = $"{game} was not find in Steam responses storage."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); continue; } var response = _steamApiClient.TryGetSteamAppAsync( appId.Value, SteamCountryCode.Russia, SteamResponseLanguage.English ).Result; if (response is null) { string message = $"{game} was not processed."; _logger.Warn(message); GlobalMessageHandler.OutputMessage(message); continue; } if (outputResults) { GlobalMessageHandler.OutputMessage($"Got {response} from \"{Tag}\"."); } searchResults.Add(response); } return(searchResults.ToList()); }
/// <summary> /// Calls reading method from inputter and process caught exceptions. /// </summary> /// <param name="inputter">Reader of input source.</param> /// <param name="storageName">Input storage name.</param> /// <param name="result">Reference to collection to write data.</param> /// <returns> /// <c>true</c> if read method doesn't throw any exceptions, <c>false</c> otherwise. /// </returns> private static bool TryReadThingNames(IInputter inputter, string storageName, out IReadOnlyList <string> result) { try { result = inputter.ReadThingNames(storageName); } catch (Exception ex) { _logger.Warn(ex, "Couldn't get access to the storage."); GlobalMessageHandler.OutputMessage("Couldn't get access to the storage for " + $"inputter {inputter.Tag}. Error: {ex}"); result = new List <string>(); return(false); } return(true); }