public async Task <IActionResult> Index([FromQuery] string algorithm, [FromQuery] bool?detailedResults, [FromQuery] bool?debugMode,
                                                [FromServices] IOptionsSnapshot <Config.RecommendationsConfig> recConfig, [FromServices] IAnimeRecsClientFactory recClientFactory)
        {
            if (!ModelState.IsValid)
            {
                string errorString = ModelBindingHelpers.ConstructErrorString(ModelState);
                _logger.LogDebug("Invalid input received for home page: {0}", errorString);
                return(View("Error", new ErrorViewModel(exception: null)));
            }

            algorithm = algorithm ?? recConfig.Value.DefaultRecSource;
            bool displayDetailedResults = detailedResults ?? false;
            bool debugModeOn            = debugMode ?? false;

            string recSourceType = null;

            using (AnimeRecsClient client = recClientFactory.GetClient(algorithm))
            {
                try
                {
                    recSourceType = await client.GetRecSourceTypeAsync(algorithm,
                                                                       TimeSpan.FromMilliseconds(recConfig.Value.TimeoutMilliseconds), CancellationToken.None);
                }
                catch
                {
                    ;
                }
            }

            bool algorithmAvailable = recSourceType != null;

            bool targetScoreNeeded = false;

            if (AnimeRecs.RecService.DTO.RecSourceTypes.AnimeRecs.Equals(recSourceType, StringComparison.OrdinalIgnoreCase) && displayDetailedResults)
            {
                targetScoreNeeded = true;
            }

            HomeViewModel viewModel = new HomeViewModel(
                algorithm: algorithm,
                algorithmAvailable: algorithmAvailable,
                targetScoreNeeded: targetScoreNeeded,
                displayDetailedResults: displayDetailedResults,
                debugModeOn: debugModeOn
                );


            return(View(viewModel));
        }
        private async Task <MalRecResults <IEnumerable <IRecommendation> > > GetRecommendationsAsync(AnimeRecsInputJson input,
                                                                                                     Config.RecommendationsConfig recConfig, Dictionary <int, MalListEntry> animeList,
                                                                                                     Dictionary <int, MalListEntry> animeWithheld, IAnimeRecsClientFactory recClientFactory)
        {
            int numRecsToTryToGet = recConfig.MaximumRecommendationsToReturn;

            if (animeWithheld.Count > 0)
            {
                // Get rating prediction information about all anime if in debug mode and withholding anime.
                // For all currently implemented algorithms, this does not cause a performance problem.
                numRecsToTryToGet = 100000;
            }

            using (AnimeRecsClient recClient = recClientFactory.GetClient(input.RecSourceName))
            {
                MalRecResults <IEnumerable <IRecommendation> > recResults;
                try
                {
                    if (input.GoodPercentile != null)
                    {
                        decimal targetFraction = input.GoodPercentile.Value / 100;
                        _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using target of top {3}%.",
                                               input.RecSourceName, numRecsToTryToGet, input.MalName, targetFraction);
                        recResults = await recClient.GetMalRecommendationsWithFractionTargetAsync(animeList,
                                                                                                  input.RecSourceName, numRecsToTryToGet, targetFraction,
                                                                                                  TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds), CancellationToken.None).ConfigureAwait(false);
                    }
                    else if (input.GoodCutoff != null)
                    {
                        _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using target of {3}.",
                                               input.RecSourceName, numRecsToTryToGet, input.MalName, input.GoodCutoff.Value);
                        recResults = await recClient.GetMalRecommendationsAsync(animeList, input.RecSourceName,
                                                                                numRecsToTryToGet, input.GoodCutoff.Value, TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds),
                                                                                CancellationToken.None).ConfigureAwait(false);
                    }
                    else
                    {
                        decimal targetFraction = recConfig.DefaultTargetPercentile / 100;
                        _logger.LogInformation("Querying rec source {0} for {1} recommendations for {2} using default target of top {3}%.",
                                               input.RecSourceName, numRecsToTryToGet, input.MalName, targetFraction);
                        recResults = await recClient.GetMalRecommendationsWithFractionTargetAsync(animeList,
                                                                                                  input.RecSourceName, numRecsToTryToGet, targetFraction,
                                                                                                  TimeSpan.FromMilliseconds(recConfig.TimeoutMilliseconds), CancellationToken.None)
                                     .ConfigureAwait(false);
                    }
                }
                catch (AnimeRecs.RecService.DTO.RecServiceErrorException ex)
                {
                    if (ex.Error.ErrorCode == AnimeRecs.RecService.DTO.ErrorCodes.Maintenance)
                    {
                        _logger.LogInformation("Could not service recommendation request for {0}. The rec service is currently undergoing maintenance.",
                                               input.MalName);
                        AjaxError  error  = new AjaxError(AjaxError.InternalError, "The site is currently undergoing scheduled maintenance. Check back in a few minutes.");
                        JsonResult result = Json(error);
                        result.StatusCode = 500;
                        throw new ShortCircuitException(result);
                    }
                    else
                    {
                        throw;
                    }
                }
                _logger.LogInformation("Got results from rec service for {0}.", input.MalName);

                return(recResults);
            }
        }
Exemple #3
0
        static void Main(string[] args)
        {
            CommandLineArgs commandLine = new CommandLineArgs(args);

            if (commandLine.ShowHelp)
            {
                commandLine.DisplayHelp(Console.Out);
                return;
            }

            using (AnimeRecsClient client = new AnimeRecsClient(commandLine.PortNumber))
            {
                if (commandLine.Operation.Equals("raw", StringComparison.OrdinalIgnoreCase))
                {
                    using (TcpClient rawClient = new TcpClient("localhost", commandLine.PortNumber))
                    {
                        byte[] jsonBytes = Encoding.UTF8.GetBytes(commandLine.RawJson);
                        rawClient.Client.Send(jsonBytes);

                        using (NetworkStream socketStream = rawClient.GetStream())
                        {
                            rawClient.Client.Shutdown(SocketShutdown.Send);
                            byte[] responseJsonBytes = StreamUtil.ReadFully(socketStream);
                            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(OpNames.Ping, StringComparison.OrdinalIgnoreCase))
                {
                    string pingResponse = client.Ping(commandLine.PingMessage);
                    Console.WriteLine("The service replied: {0}", pingResponse);
                }
                else if (commandLine.Operation.Equals(OpNames.ReloadTrainingData, StringComparison.OrdinalIgnoreCase))
                {
                    client.ReloadTrainingData(commandLine.ReloadMode, commandLine.Finalize);
                    Console.WriteLine("Training data reloaded.");
                }
                else if (commandLine.Operation.Equals(OpNames.FinalizeRecSources, StringComparison.OrdinalIgnoreCase))
                {
                    client.FinalizeRecSources();
                    Console.WriteLine("Rec sources finalized.");
                }
                else if (commandLine.Operation.Equals(OpNames.LoadRecSource, StringComparison.OrdinalIgnoreCase))
                {
                    if (commandLine.RecSourceType.Equals(RecSourceTypes.AverageScore, StringComparison.OrdinalIgnoreCase))
                    {
                        client.LoadRecSource(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource,
                            new AverageScoreRecSourceParams(
                                minEpisodesToCountIncomplete: commandLine.MinEpisodesToCountIncomplete,
                                minUsersToCountAnime: commandLine.MinUsersToCountAnime,
                                useDropped: commandLine.UseDropped
                            )
                        );
                    }
                    else if (commandLine.RecSourceType.Equals(RecSourceTypes.MostPopular, StringComparison.OrdinalIgnoreCase))
                    {
                        client.LoadRecSource(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource,
                            new MostPopularRecSourceParams(
                                minEpisodesToCountIncomplete: commandLine.MinEpisodesToCountIncomplete,
                                useDropped: commandLine.UseDropped
                            )
                        );
                    }
                    else if (commandLine.RecSourceType.Equals(RecSourceTypes.AnimeRecs, StringComparison.OrdinalIgnoreCase))
                    {
                        client.LoadRecSource(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource,
                            new AnimeRecsRecSourceParams(
                                numRecommendersToUse: commandLine.NumRecommendersToUse,
                                fractionConsideredRecommended: commandLine.FractionRecommended,
                                minEpisodesToClassifyIncomplete: commandLine.MinEpisodesToCountIncomplete
                            )
                        );
                    }
                    else if (commandLine.RecSourceType.Equals(RecSourceTypes.BiasedMatrixFactorization, StringComparison.OrdinalIgnoreCase))
                    {
                        client.LoadRecSource(commandLine.RecSourceName, commandLine.ReplaceExistingRecSource, commandLine.BiasedMatrixFactorizationParams);
                    }
                    else
                    {
                        throw new Exception("Oops! Missed a rec source type!");
                    }

                    Console.WriteLine("Load complete.");
                }
                else if (commandLine.Operation.Equals(OpNames.UnloadRecSource, StringComparison.OrdinalIgnoreCase))
                {
                    client.UnloadRecSource(commandLine.RecSourceName);
                    Console.WriteLine("Unload complete.");
                }
                else if (commandLine.Operation.Equals(OpNames.GetRecSourceType, StringComparison.OrdinalIgnoreCase))
                {
                    string recSourceType = client.GetRecSourceType(commandLine.RecSourceName);
                    Console.WriteLine("Type of rec source {0} is {1}.", commandLine.RecSourceName, recSourceType);
                }
                else if (commandLine.Operation.Equals(OpNames.GetMalRecs, StringComparison.OrdinalIgnoreCase))
                {
                    MalUserLookupResults lookup;

                    using (IMyAnimeListApi malApi = GetMalApi())
                    {
                        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);
                    }

                    MalRecResults<IEnumerable<RecEngine.IRecommendation>> recs = client.GetMalRecommendations(
                        animeList: animeListEntries,
                        recSourceName: commandLine.RecSourceName,
                        numRecsDesired: commandLine.NumRecs,
                        targetScore: commandLine.TargetScore);

                    PrintRecs(recs, animeListEntries, commandLine.TargetScore);
                }
                else
                {
                    throw new Exception(string.Format("Oops, missed an operation: {0}", commandLine.Operation));
                }
            }
        }
Exemple #4
0
        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));
                }
            }
        }
Exemple #5
0
        static void Main(string[] args)
        {
            System.Threading.Thread.CurrentThread.Name = "Main";
            Logging.SetUpLogging();

            try
            {
                CommandLineArgs commandLine = new CommandLineArgs(args);
                if (commandLine.ShowHelp)
                {
                    commandLine.DisplayHelp(Console.Out);
                    return;
                }

                ConfigRoot config = null;
                if (commandLine.ConfigFile != null)
                {
                    config = ConfigRoot.LoadFromFile(commandLine.ConfigFile);
                }

                string connectionString = ConfigurationManager.ConnectionStrings["Postgres"].ToString();
                PgMalTrainingDataLoaderFactory trainingDataLoaderFactory = new PgMalTrainingDataLoaderFactory(connectionString);
                using (TcpRecService recService = new TcpRecService(trainingDataLoaderFactory, commandLine.PortNumber))
                {
                    recService.Start();

                    if (config != null)
                    {
                        using (AnimeRecsClient client = new AnimeRecsClient(commandLine.PortNumber))
                        {
                            foreach (DTO.LoadRecSourceRequest recSourceToLoad in config.RecSources)
                            {
                                client.LoadRecSource(recSourceToLoad);
                            }

                            if (config.FinalizeAfterLoad)
                            {
                                client.FinalizeRecSources();
                            }
                        }
                    }

            #if MONO
                    Logging.Log.InfoFormat("Started listening on port {0}. Press ctrl+c to stop.", commandLine.PortNumber);
                    WaitForUnixStopSignal();
            #else

                    Logging.Log.InfoFormat("Started listening on port {0}. Press any key to stop.", commandLine.PortNumber);
                    Console.ReadKey();
            #endif

                    Logging.Log.InfoFormat("Got stop signal.");
                }
                Logging.Log.InfoFormat("Shutdown complete.");
            }
            catch (Exception ex)
            {
                Logging.Log.FatalFormat("Fatal error: {0}", ex, ex.Message);
                Environment.ExitCode = 1;
            }
        }