jameslieu / howlongtobeat

A simple wrapper API to fetch data from HowLongToBeat.com - published on Nuget
https://www.nuget.org/packages/HowLongToBeat/
MIT License
2 stars 3 forks source link

Example No Longer Works #5

Open Saious119 opened 1 year ago

Saious119 commented 1 year ago

As the title says, the example no longer works, is this package now broken/depricated?

gabuscuv commented 1 year ago

Hi @Saious119 You can use my fork, but the NuGet package is not working until @jameslieu doesn't merge my PR (I tried not to break any API/ABI, So It should be a drop-in solution) or He implements their own fixes. https://github.com/jameslieu/howlongtobeat/pull/7

morphinapg commented 1 year ago

Hi @Saious119 You can use my fork, but the NuGet package is not working until @jameslieu doesn't merge my PR (I tried not to break any API/ABI, So It should be a drop-in solution) or He implements their own fixes. #7

I tried your fork but I kept getting empty results. Anyway, looking at the code it doesn't look like it will quite be able to do everything I want from it.

I'm designing an app that makes use of all 4 times listed for each of Average, Leisure, and Rushed. So 12 values total. Ideally, I'd also want them as a double representing the number of hours in decimal form (so like 0.2 hours for 12 minutes), rather than a string.

I edit video games into movies for my youtube channel, and I've created a neural network that makes a prediction for how long my movie edit will be, based on those 12 values. Right now I just have to type them all in manually, and this is getting tedious for the large number of entries I've added over the years, so a way to automatically update my data would be ideal.

gabuscuv commented 1 year ago

Hi @Saious119 You can use my fork, but the NuGet package is not working until @jameslieu doesn't merge my PR (I tried not to break any API/ABI, So It should be a drop-in solution) or He implements their own fixes. #7

I tried your fork but I kept getting empty results. Anyway, looking at the code it doesn't look like it will quite be able to do everything I want from it.

I'm designing an app that makes use of all 4 times listed for each of Average, Leisure, and Rushed. So 12 values total. Ideally, I'd also want them as a double representing the number of hours in decimal form (so like 0.2 hours for 12 minutes), rather than a string.

I edit video games into movies for my youtube channel, and I've created a neural network that makes a prediction for how long my movie edit will be, based on those 12 values. Right now I just have to type them all in manually, and this is getting tedious for the large number of entries I've added over the years, so a way to automatically update my data would be ideal.

Technically, My Fork uses internal decimal but for respect, the ABI/API is converted to a String. (And Anyway, you can make a parse to String to Decimal in the worst case.) As you can see here: https://github.com/gabuscuv/howlongtobeat/blob/ee0ccec78ffc56548b4064ac057478e5293cb473/HowLongToBeat/DTO/Game.cs#L65

I recently re-run the unit tests, It looks all fine to me. (but for an occasional error about illegal User-Agent String for a fault in the User-Agent random generator).

Make sure the name of the game that you are looking for is right written and appears in HLTB.

morphinapg commented 10 months ago

Make sure the name of the game that you are looking for is right written and appears in HLTB.

Am I doing something wrong? I downloaded your code, built it and created a nupkg, which I then added to my app. When I tested it, I did this:

var hltb = new HowLongToBeat.HLTBWebScraper(new System.Net.Http.HttpClient());

var results = await hltb.Search("Assassin's Creed");

and got zero results. Obviously there should be several games with the title Assassin's Creed. Is there any way to jump straight to the game if you know the game's ID from the URL?

Also, is there any way to get the more detailed numbers I mentioned earlier? The ones from this box:

image

These are the numbers I use in my app. Right now I just have to manually type them in, and I'm just rounding to the nearest 15 minutes (so like, 31.5 for average completionist). If I could have them fetched automatically, and done in a more precise decimal, it would save a lot of time for me.

Perhaps I should just look into figuring out how to do a web scraper myself for my specific purpose

EDIT: Managed to figure out my own solution. I'm using AngleSharp. Here's what I did, if anybody is curious (note, I don't use the Median section for my app, just average, so I skipped that part when reading the data):

async Task<List<double?>> scraper(int GameID)
{

    var context = BrowsingContext.New(Configuration.Default.WithDefaultLoader().WithJs());
    var document = await context.OpenAsync("https://howlongtobeat.com/game/" + GameID);

    //Grab table of detailed gameplay times
    var sheets = document.GetElementsByClassName("spreadsheet").ToList();

    var MainStory = sheets.Where(x => x.InnerHtml.Contains("Main Story")).First();
    var MainPlusExtras = sheets.Where(x => x.InnerHtml.Contains("Main + Extras")).First();
    var Completionist = sheets.Where(x => x.InnerHtml.Contains("Completionist")).First();
    var AllPlayStayles = sheets.Where(x => x.InnerHtml.Contains("All PlayStyles")).First();

    //Create a list of Gameplay times for Average, Rushed, and Leisure
    var AllCells = new List<string>();

    for (int i = 2; i < 6; i++)
    {
        if (i != 3)
        {
            AllCells.Add(MainStory.Children[i].InnerHtml);
            AllCells.Add(MainPlusExtras.Children[i].InnerHtml);
            AllCells.Add(Completionist.Children[i].InnerHtml);
            AllCells.Add(AllPlayStayles.Children[i].InnerHtml);
        }
    }

    //Parse text into double values

    var AllValues = new List<double?>();

    foreach (var text in AllCells)
    {
        int
            HourPart = 0,
            MinutePart = 0;

        if (text.Contains("h") && text.Contains("m"))
        {
            var HourIndex = text.IndexOf("h");
            var MinuteIndex = text.IndexOf("m");
            var HourText = text.Substring(0, HourIndex);
            var MinuteText = text.Substring(HourIndex + 1, MinuteIndex - HourIndex - 1);

            HourPart = int.Parse(HourText);
            MinutePart = int.Parse(MinuteText);
        }
        else if (text.Contains("h"))
        {
            var HourIndex = text.IndexOf("h");
            var HourText = text.Substring(0, HourIndex);
            HourPart = int.Parse(HourText);
        }
        else if (text.Contains("m"))
        {
            var MinuteIndex = text.IndexOf("m");
            var MinuteText = text.Substring(0, MinuteIndex);
            MinutePart = int.Parse(MinuteText);
        }

        double Time = HourPart + (double)MinutePart / 60;

        if (Time > 0)
            AllValues.Add(Time);
        else
            AllValues.Add(null);
    }

    return AllValues;
}

public async Task FetchHLTBData()
{
    if (GameID.HasValue)
    {
        var HLTBData = await scraper((int)GameID);

        MainStory = HLTBData[0];
        MainPlusExtras = HLTBData[1];
        Completionist = HLTBData[2];
        AllStyles = HLTBData[3];
        RushedMain = HLTBData[4];
        RushedMainPlus = HLTBData[5];
        RushedCompletionist = HLTBData[6];
        RushedAll = HLTBData[7];
        SlowMain = HLTBData[8];
        SlowMainPlus = HLTBData[9];
        SlowCompletionist = HLTBData[10];
        SlowAll = HLTBData[11];
    }
}