public async Task <IResult <IReadOnlyCollection <byte> > > HandleAsync(GetHeatMapCommand command)
        {
            var validationResult = await IsValidAsync(command);

            if (validationResult.HasFailed())
            {
                return(validationResult.Map <IReadOnlyCollection <byte> >());
            }

            var userId     = command.UserId ?? command.CurrentUserId;
            var gamesCount = await _dataContext.Users.Where(x => x.Id == userId).Select(x => x.Games).CountAsync();

            var existingActualHeatMap = await _dataContext.GeneratedHeatMaps
                                        .AsNoTracking()
                                        .FirstOrDefaultAsync(x => x.UserId == userId && x.GeneratedAt > DateTime.Now.AddDays(-1));

            if (existingActualHeatMap != null && existingActualHeatMap.GamesCount == gamesCount)
            {
                return(existingActualHeatMap.HeatMap.ToList().ToSuccessfulResult());
            }

            PythonScriptRunner.RunScript("PythonScripts/heatmap.py", userId.ToString());

            var fileInfo = new FileInfo("heatplot.png");

            var data = new byte[fileInfo.Length];

            await using (var fs = fileInfo.OpenRead())
            {
                fs.Read(data, 0, data.Length);
            }

            fileInfo.Delete();

            _dataContext.GeneratedHeatMaps.Add(new GeneratedHeatmap
            {
                HeatMap     = data,
                UserId      = userId,
                GeneratedAt = DateTime.Now,
                GamesCount  = gamesCount
            });

            await _dataContext.SaveChangesAsync();

            return(data.ToList().ToSuccessfulResult());
        }
        public async Task <IResult <IReadOnlyCollection <GameWithImageResponse> > > HandleAsync(GetRecommendedGamesCommand command)
        {
            var validationResult = await IsValidAsync(command);

            if (validationResult.HasFailed())
            {
                return(validationResult.Map <IReadOnlyCollection <GameWithImageResponse> >());
            }

            var userId = command.UserId ?? command.CurrentUserId;

            var yesterday = DateTime.Now.AddDays(-1);
            var existingActualRecommendation = await _dataContext.GamesRecommendations
                                               .AsNoTracking()
                                               .Include(x => x.RecommendedGames)
                                               .FirstOrDefaultAsync(x => x.UserId == userId && x.GeneratedAt > yesterday);

            if (existingActualRecommendation != null && existingActualRecommendation.RecommendedGames.Count > 0)
            {
                var recommendedGamesIds = existingActualRecommendation.RecommendedGames.Select(x => x.GameId);
                var games = await _dataContext.Games
                            .Include(x => x.CoverGameImage)
                            .Where(x => recommendedGamesIds.Contains(x.Id))
                            .ToListAsync();

                return(games.Select(x => new GameWithImageResponse
                {
                    Category = x.GameCategory,
                    Id = x.Id,
                    ImageBytes = x.CoverGameImage.Data.ToList(),
                    Title = x.Name
                })
                       .ToList()
                       .ToSuccessfulResult());
            }

            PythonScriptRunner.RunScript("PythonScripts/recommender.py", userId.ToString());

            var lines = File.ReadAllLines("PythonScripts/list_of_games.txt");

            var recommendedGames = new List <Game>();

            foreach (var line in lines)
            {
                var game = await _dataContext.Games
                           .Include(x => x.CoverGameImage)
                           .SingleOrDefaultAsync(x => x.Name == line);

                if (game != null)
                {
                    recommendedGames.Add(game);
                }
            }

            var gamesRecommendation = new GamesRecommendation
            {
                GeneratedAt      = DateTime.Now,
                UserId           = userId,
                RecommendedGames = recommendedGames
                                   .Select(x => new RecommendationEntry {
                    Game = x
                }).ToList()
            };

            _dataContext.GamesRecommendations.Add(gamesRecommendation);
            await _dataContext.SaveChangesAsync();

            return(recommendedGames.Select(x => new GameWithImageResponse
            {
                Category = x.GameCategory,
                Id = x.Id,
                ImageBytes = x.CoverGameImage.Data.ToList(),
                Title = x.Name
            })
                   .ToList()
                   .ToSuccessfulResult());
        }