public async Task <float> CalculateExpectedPointsAsync(Element element)
        {
            var fplWebApiClient = new WebApiClient();
            ElementSummaryResponse elementSummaryResponse = await fplWebApiClient.GetElementSummaryAsync(element.Id);

            float minutesPlayed  = elementSummaryResponse.History.Sum(h => h.Minutes);
            float ninetiesPlayed = minutesPlayed / 90;

            float yellowCards              = element.YellowCards;
            float yellowCardsPerNinety     = yellowCards / ninetiesPlayed;
            float expectedYellowCardPoints = (yellowCardsPerNinety * PointsPerYellowCard);
            float redCards              = element.RedCards;
            float redCardsPerNinety     = redCards / ninetiesPlayed;
            float expectedRedCardPoints = (redCardsPerNinety * PointsPerRedCard);

            // Goals contribution
            // TODO: consider discounting (100% for last 6 down to 50% for 20 games ago?)
            float pointsPerGoal  = PointsPerGoal(element.ElementType);
            float goals          = element.GoalsScored;
            float goalsPerNinety = goals / ninetiesPlayed;
            float expectedPointsFromGoalsOnHistory = pointsPerGoal * goalsPerNinety;

            float expectedGoalsPerThreat = ExpectedGoalsPerThreat(element.ElementType);
            float threat                          = elementSummaryResponse.History.Sum(h => float.Parse(h.Threat));
            float threatPerNinety                 = threat / ninetiesPlayed;
            float expectedGoalsFromThreat         = threatPerNinety / expectedGoalsPerThreat;
            float expectedPointsFromGoalsOnThreat = pointsPerGoal * expectedGoalsFromThreat;

            float expectedPointsFromGoals =
                (expectedPointsFromGoalsOnHistory * HistoryGoalsFactor) +
                (expectedPointsFromGoalsOnThreat * ThreatGoalsFactor);

            return(expectedYellowCardPoints +
                   expectedRedCardPoints +
                   expectedPointsFromGoals);
        }
        public async Task Make(WebApiClient fplWebApiClient, StaticResponse staticResponse, string path)
        {
            IEnumerable <Fixture> fixtures = await fplWebApiClient.GetFixturesAsync();

            using (StreamWriter writer = new StreamWriter(File.Create(path)))
            {
                writer.WriteLine("event_id,player_id,player_name,difficulty,home,points");

                int progress = 0;
                int max      = staticResponse.Elements.Count();
                foreach (Element element in staticResponse.Elements)
                {
                    Console.WriteLine($"Predicting {++progress} of {max}");

                    ElementSummaryResponse elementResponse = await fplWebApiClient.GetElementSummaryAsync(element.Id);

                    if (elementResponse == null)
                    {
                        continue;
                    }

                    ElementHistoryPast history2017 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2017/18");
                    ElementHistoryPast history2018 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2018/19");
                    ElementHistoryPast history2019 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2019/20");

                    ModelInput fixtureData = new ModelInput()
                    {
                        Isvalid2017    = (history2017 == null) ? 0 : 1,
                        Minutes2017    = (history2017 == null) ? 0 : history2017.Minutes,
                        Points2017     = (history2017 == null) ? 0 : history2017.TotalPoints,
                        Influence2017  = (history2017 == null) ? 0 : float.Parse(history2017.Influence),
                        Creativity2017 = (history2017 == null) ? 0 : float.Parse(history2017.Creativity),
                        Threat2017     = (history2017 == null) ? 0 : float.Parse(history2017.Threat),
                        Isvalid2018    = (history2018 == null) ? 0 : 1,
                        Minutes2018    = (history2018 == null) ? 0 : history2018.Minutes,
                        Points2018     = (history2018 == null) ? 0 : history2018.TotalPoints,
                        Influence2018  = (history2018 == null) ? 0 : float.Parse(history2018.Influence),
                        Creativity2018 = (history2018 == null) ? 0 : float.Parse(history2018.Creativity),
                        Threat2018     = (history2018 == null) ? 0 : float.Parse(history2018.Threat),
                        Isvalid2019    = (history2019 == null) ? 0 : 1,
                        Minutes2019    = (history2019 == null) ? 0 : history2019.Minutes,
                        Points2019     = (history2019 == null) ? 0 : history2019.TotalPoints,
                        Influence2019  = (history2019 == null) ? 0 : float.Parse(history2019.Influence),
                        Creativity2019 = (history2019 == null) ? 0 : float.Parse(history2019.Creativity),
                        Threat2019     = (history2019 == null) ? 0 : float.Parse(history2019.Threat),

                        Playerid     = element.Id,
                        Teamid       = element.Team,
                        Position     = element.ElementType,
                        Selectedby   = float.Parse(element.SelectedByPercent),
                        Transfersin  = element.TransfersInEvent,
                        Transfersout = element.TransfersOutEvent,
                        Diff         = 2F,
                        Home         = "0",
                        Value        = element.NowCost
                    };

                    foreach (ElementHistory history in elementResponse.History)
                    {
                        Fixture gwFixture = fixtures.Single(f => f.Id == history.FixtureId);
                        AddPreviousGameweekToInput(fixtureData, history, gwFixture, staticResponse.CurrentEvent);
                    }

                    foreach (ElementFixture fixture in elementResponse.Fixtures.Take(5))
                    {
                        fixtureData.Diff = fixture.Difficulty;
                        fixtureData.Home = fixture.IsHome ? "1" : "0";

                        var predictionResult = ConsumeModel.Predict(fixtureData);

                        writer.WriteLine($"{fixture.EventId},{element.Id},{element.FirstName} {element.SecondName},{fixtureData.Diff},{fixtureData.Home},{predictionResult.Score}");
                    }
                }
            }
        }
예제 #3
0
        public async Task Build(WebApiClient fplWebApiClient, StaticResponse staticResponse, string path)
        {
            IEnumerable <Fixture> fixtures = await fplWebApiClient.GetFixturesAsync();

            using (StreamWriter writer = new StreamWriter(File.Create(path)))
            {
                Event currentEvent         = staticResponse.Events.Single(e => e.IsCurrent);
                int   numPreviousGameweeks = currentEvent.Id - 1;

                string gameweeksHeader = BuildGameweeksHeader(currentEvent.Id);
                writer.WriteLine($"{PreviousSeason.GetHeaderRow("2017")},{PreviousSeason.GetHeaderRow("2018")},{PreviousSeason.GetHeaderRow("2019")},{gameweeksHeader},playerid,teamid,position,selectedby,transfersin,transfersout,diff,home,value,points");

                int progress = 0;
                //IEnumerable<Element> elementsToProcess = staticResponse.Elements.Take(50);
                IEnumerable <Element> elementsToProcess = staticResponse.Elements;
                int max = elementsToProcess.Count();
                foreach (Element element in elementsToProcess)
                {
                    Console.WriteLine($"Processing {++progress} of {max}");

                    ElementSummaryResponse elementResponse = await fplWebApiClient.GetElementSummaryAsync(element.Id);

                    if (elementResponse == null)
                    {
                        continue;
                    }

                    ElementHistoryPast history2017 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2017/18");
                    ElementHistoryPast history2018 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2018/19");
                    ElementHistoryPast history2019 = elementResponse.HistoryPast.SingleOrDefault(hp => hp.SeasonName == "2019/20");

                    PreviousSeason season2017 = BuildPreviousSeason(history2017);
                    PreviousSeason season2018 = BuildPreviousSeason(history2018);
                    PreviousSeason season2019 = BuildPreviousSeason(history2019);

                    // First pass to build all previous match data by gameweek
                    var previousMatchesByGameweek = new Dictionary <int, PreviousMatch>();
                    foreach (ElementHistory history in elementResponse.History)
                    {
                        // TODO: add support for multi-match weeks
                        if (previousMatchesByGameweek.ContainsKey(history.Round))
                        {
                            continue;
                        }

                        Fixture       fixture  = fixtures.Single(f => f.Id == history.FixtureId);
                        PreviousMatch gameweek = BuildPreviousMatch(history, fixture);

                        previousMatchesByGameweek.Add(history.Round, gameweek);
                    }

                    PreviousMatch gameweekNull = BuildPreviousMatch(null, null);

                    foreach (ElementHistory history in elementResponse.History)
                    {
                        TrainingDataRow row = new TrainingDataRow();
                        row.Season2017 = season2017;
                        row.Season2018 = season2018;
                        row.Season2019 = season2019;

                        row.PreviousGameweeks = new PreviousMatch[numPreviousGameweeks];
                        int previousRound = history.Round - 1;
                        for (int round = 0; round < numPreviousGameweeks; ++round)
                        {
                            if (previousMatchesByGameweek.ContainsKey(previousRound))
                            {
                                row.PreviousGameweeks[round] = previousMatchesByGameweek[previousRound];
                            }
                            else
                            {
                                row.PreviousGameweeks[round] = gameweekNull;
                            }

                            --previousRound;
                        }

                        Fixture fixture = fixtures.Single(f => f.Id == history.FixtureId);
                        row.AtHome = history.WasHome ? 1 : 0;
                        if (history.WasHome)
                        {
                            row.Difficulty = fixture.HomeTeamDifficulty;
                        }
                        else
                        {
                            row.Difficulty = fixture.AwayTeamDifficulty;
                        }
                        row.Value       = history.Value;
                        row.TotalPoints = history.TotalPoints;

                        string seasonsData = $"{row.Season2017},{row.Season2018},{row.Season2019}";
                        var    previousGameweeksBuilder = new StringBuilder();
                        for (int round = 0; round < numPreviousGameweeks; ++round)
                        {
                            previousGameweeksBuilder.Append(row.PreviousGameweeks[round]);
                            if (round < (numPreviousGameweeks - 1))
                            {
                                previousGameweeksBuilder.Append(",");
                            }
                        }
                        string gameweeksData = previousGameweeksBuilder.ToString();
                        string otherData     = $"{element.Id},{element.Team},{element.ElementType},{element.SelectedByPercent:F1},{history.TransfersIn:F1},{history.TransfersOut:F1},{row.Difficulty},{row.AtHome},{row.Value:F1},{row.TotalPoints:F1}";
                        writer.WriteLine($"{seasonsData},{gameweeksData},{otherData}");
                    }
                }
            }
        }