public void PrintResults(MalRecResults<IEnumerable<IRecommendation>> results, IDictionary<int, MalListEntry> animeList, decimal targetScore) { if (RegisteredPrinters.ContainsKey(results.RecommendationType)) { RegisteredPrinters[results.RecommendationType](results, animeList, targetScore); } else { PrintFallbackResults(results, animeList, targetScore); } }
public void PrintResults(MalRecResults <IEnumerable <IRecommendation> > results, IDictionary <int, MalListEntry> animeList, decimal targetScore) { if (RegisteredPrinters.ContainsKey(results.RecommendationType)) { RegisteredPrinters[results.RecommendationType](results, animeList, targetScore); } else { PrintFallbackResults(results, animeList, targetScore); } }
public async Task <IActionResult> GetRecs([FromBody] AnimeRecsInputJson input, [FromServices] IOptionsSnapshot <Config.RecommendationsConfig> recConfig, [FromServices] IMyAnimeListApiFactory malApiFactory, [FromServices] IAnimeRecsClientFactory recClientFactory, [FromServices] IAnimeRecsDbConnectionFactory dbConnFactory, [FromServices] IRazorViewEngine viewEngine, [FromServices] ITempDataProvider tempProvider) { if (!ModelState.IsValid) { AjaxError error = new AjaxError(ModelState); _logger.LogDebug("Invalid input received for GetRecs: {0}", error.Message); return(BadRequest(error)); } if (input.RecSourceName == null) { input.RecSourceName = recConfig.Value.DefaultRecSource; } try { MalUserLookupResults userLookup = await GetUserLookupAsync(input, malApiFactory).ConfigureAwait(false); Dictionary <int, MalListEntry> animeList = new Dictionary <int, MalListEntry>(); foreach (MyAnimeListEntry listEntry in userLookup.AnimeList) { animeList[listEntry.AnimeInfo.AnimeId] = new AnimeRecs.RecEngine.MAL.MalListEntry((byte?)listEntry.Score, listEntry.Status, (short)listEntry.NumEpisodesWatched); } Dictionary <int, MalListEntry> animeWithheld = WithholdAnime(input, animeList); MalRecResults <IEnumerable <IRecommendation> > recResults = await GetRecommendationsAsync(input, recConfig.Value, animeList, animeWithheld, recClientFactory).ConfigureAwait(false); GetRecsViewModel viewModel = new GetRecsViewModel( results: recResults, userId: userLookup.UserId, userName: userLookup.CanonicalUserName, userLookup: userLookup, userAnimeList: animeList, maximumRecommendationsToReturn: recConfig.Value.MaximumRecommendationsToReturn, maximumRecommendersToReturn: recConfig.Value.MaximumRecommendersToReturn, animeWithheld: animeWithheld, dbConnectionFactory: dbConnFactory ); RecResultsAsHtmlJson resultsJson = await GetResultHtmlAsync(viewModel, input, viewEngine, tempProvider).ConfigureAwait(false); return(Ok(resultsJson)); } catch (ShortCircuitException ex) { return(ex.Result); } }
private static void PrintRecs(MalRecResults <IEnumerable <RecEngine.IRecommendation> > recs, IDictionary <int, RecEngine.MAL.MalListEntry> animeList, decimal targetScore) { if (!recs.Results.Any()) { Console.WriteLine("No recommendations."); return; } ResultsPrinter resultsPrinter = new ResultsPrinter(); resultsPrinter.PrintResults(recs, animeList, targetScore); }
public GetRecsViewModel(MalRecResults<IEnumerable<IRecommendation>> results, int userId, string userName, MalUserLookupResults userLookup, IDictionary<int, MalListEntry> userAnimeList, int maximumRecommendationsToReturn, int maximumRecommendersToReturn, IDictionary<int, MalListEntry> animeWithheld, IAnimeRecsDbConnectionFactory dbConnectionFactory) { Results = results; UserId = userId; UserName = userName; UserLookup = userLookup; UserAnimeList = userAnimeList; MaximumRecommendationsToReturn = maximumRecommendationsToReturn; MaximumRecommendersToReturn = maximumRecommendersToReturn; DbConnectionFactory = dbConnectionFactory; StreamsByAnime = new Dictionary<int, ICollection<streaming_service_anime_map>>(); AnimeWithheld = animeWithheld; }
private void PrintRatingPredictionResults(MalRecResults<IEnumerable<IRecommendation>> basicResults, IDictionary<int, MalListEntry> animeList, decimal targetScore) { MalRecResults<IEnumerable<RatingPredictionRecommendation>> results = basicResults.CastRecs<IEnumerable<RatingPredictionRecommendation>>(); int recNumber = 1; foreach (var recIt in results.Results.AsSmartEnumerable()) { RatingPredictionRecommendation rec = recIt.Value; if (recIt.IsFirst) { Console.WriteLine(" {0,-60} {1}", "Anime", "Prediction"); } Console.WriteLine("{0,3}. {1,-60} {2:F3}", recNumber, results.AnimeInfo[rec.ItemId].Title, rec.PredictedRating); recNumber++; } }
private void PrintRatingPredictionResults(MalRecResults <IEnumerable <IRecommendation> > basicResults, IDictionary <int, MalListEntry> animeList, decimal targetScore) { MalRecResults <IEnumerable <RatingPredictionRecommendation> > results = basicResults.CastRecs <IEnumerable <RatingPredictionRecommendation> >(); int recNumber = 1; foreach (RatingPredictionRecommendation rec in results.Results) { if (recNumber == 1) { Console.WriteLine(" {0,-60} {1}", "Anime", "Prediction"); } Console.WriteLine("{0,3}. {1,-60} {2:F3}", recNumber, results.AnimeInfo[rec.ItemId].Title, rec.PredictedRating); recNumber++; } }
private void PrintFallbackResults(MalRecResults <IEnumerable <IRecommendation> > results, IDictionary <int, MalListEntry> animeList, decimal targetScore) { int recNumber = 1; foreach (IRecommendation rec in results.Results) { if (recNumber == 1) { Console.WriteLine(" {0,-65}", "Anime"); } Console.WriteLine("{0,3}. {1.-65}", recNumber, results.AnimeInfo[rec.ItemId].Title); recNumber++; } }
private void PrintFallbackResults(MalRecResults<IEnumerable<IRecommendation>> results, IDictionary<int, MalListEntry> animeList, decimal targetScore) { int recNumber = 1; foreach (var recIt in results.Results.AsSmartEnumerable()) { IRecommendation rec = recIt.Value; if (recIt.IsFirst) { Console.WriteLine(" {0,-65}", "Anime"); } Console.WriteLine("{0,3}. {1.-65}", recNumber, results.AnimeInfo[rec.ItemId].Title); recNumber++; } }
public GetRecsViewModel(MalRecResults <IEnumerable <IRecommendation> > results, int userId, string userName, MalUserLookupResults userLookup, IDictionary <int, MalListEntry> userAnimeList, int maximumRecommendationsToReturn, int maximumRecommendersToReturn, IDictionary <int, MalListEntry> animeWithheld, IAnimeRecsDbConnectionFactory dbConnectionFactory) { Results = results; UserId = userId; UserName = userName; UserLookup = userLookup; UserAnimeList = userAnimeList; MaximumRecommendationsToReturn = maximumRecommendationsToReturn; MaximumRecommendersToReturn = maximumRecommendersToReturn; DbConnectionFactory = dbConnectionFactory; StreamsByAnime = new Dictionary <int, ICollection <streaming_service_anime_map> >(); AnimeWithheld = animeWithheld; }
private void PrintAverageScoreResults(MalRecResults <IEnumerable <IRecommendation> > basicResults, IDictionary <int, MalListEntry> animeList, decimal targetScore) { MalRecResults <IEnumerable <AverageScoreRecommendation> > results = basicResults.CastRecs <IEnumerable <AverageScoreRecommendation> >(); int recNumber = 1; foreach (AverageScoreRecommendation rec in results.Results) { if (recNumber == 1) { Console.WriteLine(" {0,-52} {1,-6} {2}", "Anime", "Avg", "# ratings"); } Console.WriteLine("{0,3}. {1,-52} {2,-6:f2} {3}", recNumber, results.AnimeInfo[rec.ItemId].Title, rec.AverageScore, rec.NumRatings); recNumber++; } }
private void PrintMostPopularResults(MalRecResults<IEnumerable<IRecommendation>> basicResults, IDictionary<int, MalListEntry> animeList, decimal targetScore) { MalRecResults<IEnumerable<MostPopularRecommendation>> results = basicResults.CastRecs<IEnumerable<MostPopularRecommendation>>(); int recNumber = 1; foreach (var recIt in results.Results.AsSmartEnumerable()) { MostPopularRecommendation rec = recIt.Value; if (recIt.IsFirst) { Console.WriteLine(" {0,-52} {1,4} {2}", "Anime", "Rank", "# ratings"); } Console.WriteLine("{0,3}. {1,-52} {2,4} {3}", recNumber, results.AnimeInfo[rec.ItemId].Title, rec.PopularityRank, rec.NumRatings); recNumber++; } }
private void PrintAnimeRecsResults(MalRecResults<IEnumerable<IRecommendation>> basicResults, IDictionary<int, MalListEntry> animeList, decimal targetScore) { MalRecResults<MalAnimeRecsResults> results = basicResults.CastRecs<MalAnimeRecsResults>(); int numRecommendersPrinted = 0; foreach (MalAnimeRecsRecommenderUser recommender in results.Results.Recommenders) { if (numRecommendersPrinted > 10) { break; } string recsLikedString; if (recommender.NumRecsWithJudgment > 0) { recsLikedString = string.Format("{0:P2}", (double)recommender.RecsLiked.Count / recommender.NumRecsWithJudgment); } else { recsLikedString = string.Format("{0:P2}", 0); } Console.WriteLine("{0}'s recommendations ({1}/{2} {3} recs liked, {4:P2} - {5:P2} estimated compatibility", recommender.Username, recommender.RecsLiked.Count, recommender.NumRecsWithJudgment, recsLikedString, recommender.CompatibilityLowEndpoint ?? 0, recommender.CompatibilityHighEndpoint ?? 0); Console.WriteLine("{0,-52} {1,-5} {2,-4} {3,-5} {4,-4} {5}", "Anime", "State", "Like", "Their", "Your", "Avg"); foreach (MalAnimeRecsRecommenderRecommendation recommendation in recommender.AllRecommendations.OrderBy( rec => !recommender.RecsLiked.Contains(rec) && !recommender.RecsNotLiked.Contains(rec) ? 0 : recommender.RecsLiked.Contains(rec) ? 1 : 2 ) .ThenByDescending(rec => rec.RecommenderScore) .ThenByDescending(rec => rec.AverageScore)) { string status; decimal? yourRating = null; if (!animeList.ContainsKey(recommendation.MalAnimeId)) { status = "-"; // not watched, not in list } else { if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Completed) status = "comp"; else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Dropped) status = "drop"; else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.OnHold) status = "hold"; else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.PlanToWatch) status = "plan"; else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Watching) status = "watch"; else status = "?"; yourRating = animeList[recommendation.MalAnimeId].Rating; } string yourRatingString; if (yourRating != null) { yourRatingString = yourRating.Value.ToString(CultureInfo.CurrentCulture); } else { yourRatingString = "-"; } string likedString; if (recommender.RecsLiked.Contains(recommendation)) likedString = "+"; else if (recommender.RecsNotLiked.Contains(recommendation)) likedString = "-"; else likedString = "?"; Console.WriteLine("{0,-52} {1,-5} {2,-4} {3,-5:F0} {4,-4:F0} {5:F2}", results.AnimeInfo[recommendation.MalAnimeId].Title, status, likedString, recommendation.RecommenderScore, yourRatingString, recommendation.AverageScore); } Console.WriteLine(); Console.WriteLine(); numRecommendersPrinted++; } }
private static void PrintRecs(MalRecResults<IEnumerable<RecEngine.IRecommendation>> recs, IDictionary<int, RecEngine.MAL.MalListEntry> animeList, decimal targetScore) { if (!recs.Results.Any()) { Console.WriteLine("No recommendations."); return; } ResultsPrinter resultsPrinter = new ResultsPrinter(); resultsPrinter.PrintResults(recs, animeList, targetScore); }
static void Main(string[] args) { CommandLineArgs commandLine = new CommandLineArgs(args); if (commandLine.ShowHelp) { commandLine.DisplayHelp(Console.Out); return; } Config config = Config.LoadFromFile(commandLine.ConfigFile); using (AnimeRecsClient client = new AnimeRecsClient(commandLine.PortNumber)) { if (commandLine.Operation.Equals("raw", StringComparison.OrdinalIgnoreCase)) { byte[] requestJsonBytes = Encoding.UTF8.GetBytes(commandLine.RawJson); int requestLength = requestJsonBytes.Length; int requestLengthNetworkOrder = IPAddress.HostToNetworkOrder(requestLength); byte[] requestLengthBytes = BitConverter.GetBytes(requestLengthNetworkOrder); byte[] requestBytes = new byte[requestLengthBytes.Length + requestJsonBytes.Length]; requestLengthBytes.CopyTo(requestBytes, index: 0); requestJsonBytes.CopyTo(requestBytes, index: requestLengthBytes.Length); using (Socket rawClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { TimeSpan sendTimeout = TimeSpan.FromSeconds(5); rawClientSocket.SendAllAsync(requestBytes, sendTimeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); rawClientSocket.Shutdown(SocketShutdown.Send); byte[] responseLengthBuffer = rawClientSocket.ReceiveAllAsync(numBytesToReceive: 4, receiveAllTimeout: TimeSpan.FromMinutes(3), cancellationToken: CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); int responseLengthNetworkOrder = BitConverter.ToInt32(responseLengthBuffer, 0); int responseLength = IPAddress.NetworkToHostOrder(responseLengthNetworkOrder); byte[] responseJsonBytes = rawClientSocket.ReceiveAllAsync(responseLength, receiveAllTimeout: TimeSpan.FromSeconds(5), cancellationToken: CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); string responseJsonString = Encoding.UTF8.GetString(responseJsonBytes); dynamic responseJson = JsonConvert.DeserializeObject <dynamic>(responseJsonString); string prettyResponse = JsonConvert.SerializeObject(responseJson, Formatting.Indented); Console.WriteLine(prettyResponse); } } else if (commandLine.Operation.Equals(OperationTypes.Ping, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(3); Stopwatch timer = Stopwatch.StartNew(); string pingResponse = client.PingAsync(commandLine.PingMessage, timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); timer.Stop(); Console.WriteLine($"The service replied: {pingResponse} (took {timer.Elapsed})"); } else if (commandLine.Operation.Equals(OperationTypes.ReloadTrainingData, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromMinutes(3); client.ReloadTrainingDataAsync(commandLine.ReloadMode, commandLine.Finalize, timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); Console.WriteLine("Training data reloaded."); } else if (commandLine.Operation.Equals(OperationTypes.FinalizeRecSources, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(5); client.FinalizeRecSourcesAsync(timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult();; Console.WriteLine("Rec sources finalized."); } else if (commandLine.Operation.Equals(OperationTypes.LoadRecSource, StringComparison.OrdinalIgnoreCase)) { if (commandLine.RecSourceType.Equals(RecSourceTypes.AverageScore, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(30); client.LoadRecSourceAsync(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource, new AverageScoreRecSourceParams( minEpisodesToCountIncomplete: commandLine.MinEpisodesToCountIncomplete, minUsersToCountAnime: commandLine.MinUsersToCountAnime, useDropped: commandLine.UseDropped ), timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); } else if (commandLine.RecSourceType.Equals(RecSourceTypes.MostPopular, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(30); client.LoadRecSourceAsync(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource, new MostPopularRecSourceParams( minEpisodesToCountIncomplete: commandLine.MinEpisodesToCountIncomplete, useDropped: commandLine.UseDropped ), timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); } else if (commandLine.RecSourceType.Equals(RecSourceTypes.AnimeRecs, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(60); client.LoadRecSourceAsync(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource, new AnimeRecsRecSourceParams( numRecommendersToUse: commandLine.NumRecommendersToUse, fractionConsideredRecommended: commandLine.FractionRecommended, minEpisodesToClassifyIncomplete: commandLine.MinEpisodesToCountIncomplete ), timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); } else if (commandLine.RecSourceType.Equals(RecSourceTypes.BiasedMatrixFactorization, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromMinutes(3); client.LoadRecSourceAsync(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource, commandLine.BiasedMatrixFactorizationParams, timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); } else { throw new Exception("Oops! Missed a rec source type!"); } Console.WriteLine("Load complete."); } else if (commandLine.Operation.Equals(OperationTypes.UnloadRecSource, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(10); client.UnloadRecSourceAsync(commandLine.RecSourceName, timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); Console.WriteLine("Unload complete."); } else if (commandLine.Operation.Equals(OperationTypes.GetRecSourceType, StringComparison.OrdinalIgnoreCase)) { TimeSpan timeout = TimeSpan.FromSeconds(3); string recSourceType = client.GetRecSourceTypeAsync(commandLine.RecSourceName, timeout, CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); Console.WriteLine("Type of rec source {0} is {1}.", commandLine.RecSourceName, recSourceType); } else if (commandLine.Operation.Equals(OperationTypes.GetMalRecs, StringComparison.OrdinalIgnoreCase)) { MalUserLookupResults lookup; using (IMyAnimeListApi malApi = GetMalApi(config)) { lookup = malApi.GetAnimeListForUser(commandLine.MalUsername); } Dictionary <int, RecEngine.MAL.MalListEntry> animeListEntries = new Dictionary <int, RecEngine.MAL.MalListEntry>(); foreach (MyAnimeListEntry entry in lookup.AnimeList) { animeListEntries[entry.AnimeInfo.AnimeId] = new RecEngine.MAL.MalListEntry((byte?)entry.Score, entry.Status, (short)entry.NumEpisodesWatched); } TimeSpan timeout = TimeSpan.FromSeconds(10); MalRecResults <IEnumerable <RecEngine.IRecommendation> > recs = client.GetMalRecommendationsAsync( animeList: animeListEntries, recSourceName: commandLine.RecSourceName, numRecsDesired: commandLine.NumRecs, targetScore: commandLine.TargetScore, timeout: timeout, cancellationToken: CancellationToken.None ) .ConfigureAwait(false).GetAwaiter().GetResult(); PrintRecs(recs, animeListEntries, commandLine.TargetScore); } else { throw new Exception(string.Format("Oops, missed an operation: {0}", commandLine.Operation)); } } }
private void PrintAnimeRecsResults(MalRecResults <IEnumerable <IRecommendation> > basicResults, IDictionary <int, MalListEntry> animeList, decimal targetScore) { MalRecResults <MalAnimeRecsResults> results = basicResults.CastRecs <MalAnimeRecsResults>(); int numRecommendersPrinted = 0; foreach (MalAnimeRecsRecommenderUser recommender in results.Results.Recommenders) { if (numRecommendersPrinted > 10) { break; } string recsLikedString; if (recommender.NumRecsWithJudgment > 0) { recsLikedString = string.Format("{0:P2}", (double)recommender.RecsLiked.Count / recommender.NumRecsWithJudgment); } else { recsLikedString = string.Format("{0:P2}", 0); } Console.WriteLine("{0}'s recommendations ({1}/{2} {3} recs liked, {4:P2} - {5:P2} estimated compatibility", recommender.Username, recommender.RecsLiked.Count, recommender.NumRecsWithJudgment, recsLikedString, recommender.CompatibilityLowEndpoint ?? 0, recommender.CompatibilityHighEndpoint ?? 0); Console.WriteLine("{0,-52} {1,-5} {2,-4} {3,-5} {4,-4} {5}", "Anime", "State", "Like", "Their", "Your", "Avg"); foreach (MalAnimeRecsRecommenderRecommendation recommendation in recommender.AllRecommendations.OrderBy( rec => !recommender.RecsLiked.Contains(rec) && !recommender.RecsNotLiked.Contains(rec) ? 0 : recommender.RecsLiked.Contains(rec) ? 1 : 2 ) .ThenByDescending(rec => rec.RecommenderScore) .ThenByDescending(rec => rec.AverageScore)) { string status; decimal?yourRating = null; if (!animeList.ContainsKey(recommendation.MalAnimeId)) { status = "-"; // not watched, not in list } else { if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Completed) { status = "comp"; } else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Dropped) { status = "drop"; } else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.OnHold) { status = "hold"; } else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.PlanToWatch) { status = "plan"; } else if (animeList[recommendation.MalAnimeId].Status == CompletionStatus.Watching) { status = "watch"; } else { status = "?"; } yourRating = animeList[recommendation.MalAnimeId].Rating; } string yourRatingString; if (yourRating != null) { yourRatingString = yourRating.Value.ToString(CultureInfo.CurrentCulture); } else { yourRatingString = "-"; } string likedString; if (recommender.RecsLiked.Contains(recommendation)) { likedString = "+"; } else if (recommender.RecsNotLiked.Contains(recommendation)) { likedString = "-"; } else { likedString = "?"; } Console.WriteLine("{0,-52} {1,-5} {2,-4} {3,-5:F0} {4,-4:F0} {5:F2}", results.AnimeInfo[recommendation.MalAnimeId].Title, status, likedString, recommendation.RecommenderScore, yourRatingString, recommendation.AverageScore); } Console.WriteLine(); Console.WriteLine(); numRecommendersPrinted++; } }