Lookup player counts from PCGamingWiki for multiplayer modes

dashboard
Pat Hartl 2023-01-14 18:22:51 -06:00
parent 11f75b02f7
commit c4ce8e14aa
8 changed files with 195 additions and 3 deletions

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="System.Text.Json" Version="5.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LANCommander.SDK\LANCommander.SDK.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,91 @@
using HtmlAgilityPack;
using LANCommander.SDK;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
namespace LANCommander.PCGamingWiki
{
public class PCGamingWikiClient
{
private HttpClient Client;
public PCGamingWikiClient()
{
Client = new HttpClient();
Client.BaseAddress = new Uri("https://www.pcgamingwiki.com/");
}
public async Task<Uri> Search(string keyword)
{
var results = await Client.GetStringAsync($"w/api.php?action=opensearch&format=json&formatversion=2&search={HttpUtility.UrlEncode(keyword)}&limit=1");
string pattern = @"(https:\/\/www.pcgamingwiki.com.+)""";
RegexOptions options = RegexOptions.Multiline;
var match = Regex.Match(results, pattern, options);
if (match.Success && match.Groups.Count == 2)
{
return new Uri(match.Groups[1].Value);
}
return null;
}
public async Task<Dictionary<string, int>> GetMultiplayerPlayerCounts(string keyword)
{
var url = await Search(keyword);
return await GetMultiplayerPlayerCounts(url);
}
public async Task<Dictionary<string, int>> GetMultiplayerPlayerCounts(Uri url)
{
var results = new Dictionary<string, int>();
HtmlWeb web = new HtmlWeb();
HtmlDocument dom = web.Load(url);
HtmlNode multiplayerTable = dom.GetElementbyId("table-network-multiplayer");
if (multiplayerTable == null)
return null;
var multiplayerAbbrs = multiplayerTable.SelectNodes(".//abbr");
var multiplayerCounts = multiplayerTable.SelectNodes(".//td[contains(@class, 'table-network-multiplayer-body-players')]");
for (int i = 0; i < multiplayerAbbrs.Count; i++)
{
var type = multiplayerAbbrs[i].InnerText;
var players = multiplayerCounts[i].InnerText;
int playerCount = 0;
if (Int32.TryParse(players, out playerCount))
{
switch (type.ToLower())
{
case "local play":
results["Local Play"] = playerCount;
break;
case "lan play":
results["LAN Play"] = playerCount;
break;
case "online play":
results["Online Play"] = playerCount;
break;
}
}
}
return results;
}
}
}

View File

@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LANCommander.PlaynitePlugin
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LANCommander.SDK", "LANCommander.SDK\LANCommander.SDK.csproj", "{4C2A71FD-A30B-4D62-888A-4EF843D8E506}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LANCommander.SDK", "LANCommander.SDK\LANCommander.SDK.csproj", "{4C2A71FD-A30B-4D62-888A-4EF843D8E506}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LANCommander.PCGamingWiki", "LANCommander.PCGamingWiki\LANCommander.PCGamingWiki.csproj", "{2436B817-4475-4E70-9BB2-E1E7866DB79F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Release|Any CPU.ActiveCfg = Release|Any CPU {4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Release|Any CPU.Build.0 = Release|Any CPU {4C2A71FD-A30B-4D62-888A-4EF843D8E506}.Release|Any CPU.Build.0 = Release|Any CPU
{2436B817-4475-4E70-9BB2-E1E7866DB79F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2436B817-4475-4E70-9BB2-E1E7866DB79F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2436B817-4475-4E70-9BB2-E1E7866DB79F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2436B817-4475-4E70-9BB2-E1E7866DB79F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -13,6 +13,7 @@ using LANCommander.Services;
using System.Drawing; using System.Drawing;
using LANCommander.Models; using LANCommander.Models;
using LANCommander.Data.Enums; using LANCommander.Data.Enums;
using LANCommander.PCGamingWiki;
namespace LANCommander.Controllers namespace LANCommander.Controllers
{ {
@ -26,6 +27,7 @@ namespace LANCommander.Controllers
private readonly GenreService GenreService; private readonly GenreService GenreService;
private readonly CompanyService CompanyService; private readonly CompanyService CompanyService;
private readonly IGDBService IGDBService; private readonly IGDBService IGDBService;
private readonly PCGamingWikiClient PCGamingWikiClient;
public GamesController(GameService gameService, ArchiveService archiveService, CategoryService categoryService, TagService tagService, GenreService genreService, CompanyService companyService, IGDBService igdbService) public GamesController(GameService gameService, ArchiveService archiveService, CategoryService categoryService, TagService tagService, GenreService genreService, CompanyService companyService, IGDBService igdbService)
{ {
@ -36,6 +38,7 @@ namespace LANCommander.Controllers
GenreService = genreService; GenreService = genreService;
CompanyService = companyService; CompanyService = companyService;
IGDBService = igdbService; IGDBService = igdbService;
PCGamingWikiClient = new PCGamingWikiClient();
} }
// GET: Games // GET: Games
@ -57,7 +60,12 @@ namespace LANCommander.Controllers
if (igdbid == null) if (igdbid == null)
{ {
viewModel.Game = new Game(); viewModel.Game = new Game()
{
Actions = new List<Data.Models.Action>(),
MultiplayerModes = new List<Data.Models.MultiplayerMode>()
};
viewModel.Developers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList(); viewModel.Developers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList();
viewModel.Publishers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList(); viewModel.Publishers = CompanyService.Get().OrderBy(c => c.Name).Select(c => new SelectListItem() { Text = c.Name, Value = c.Name }).ToList();
viewModel.Genres = GenreService.Get().OrderBy(g => g.Name).Select(g => new SelectListItem() { Text = g.Name, Value = g.Name }).ToList(); viewModel.Genres = GenreService.Get().OrderBy(g => g.Name).Select(g => new SelectListItem() { Text = g.Name, Value = g.Name }).ToList();
@ -74,9 +82,42 @@ namespace LANCommander.Controllers
Title = result.Name, Title = result.Name,
Description = result.Summary, Description = result.Summary,
ReleasedOn = result.FirstReleaseDate.GetValueOrDefault().UtcDateTime, ReleasedOn = result.FirstReleaseDate.GetValueOrDefault().UtcDateTime,
MultiplayerModes = new List<MultiplayerMode>(), Actions = new List<Data.Models.Action>(),
MultiplayerModes = new List<MultiplayerMode>()
}; };
var playerCounts = await PCGamingWikiClient.GetMultiplayerPlayerCounts(result.Name);
foreach (var playerCount in playerCounts)
{
MultiplayerType type;
switch (playerCount.Key)
{
case "Local Play":
type = MultiplayerType.Local;
break;
case "LAN Play":
type = MultiplayerType.Lan;
break;
case "Online Play":
type = MultiplayerType.Online;
break;
default:
continue;
}
viewModel.Game.MultiplayerModes.Add(new MultiplayerMode()
{
Type = type,
MaxPlayers = playerCount.Value,
MinPlayers = 2
});
}
if (result.GameModes != null && result.GameModes.Values != null) if (result.GameModes != null && result.GameModes.Values != null)
viewModel.Game.Singleplayer = result.GameModes.Values.Any(gm => gm.Name == "Singleplayer"); viewModel.Game.Singleplayer = result.GameModes.Values.Any(gm => gm.Name == "Singleplayer");

View File

@ -49,6 +49,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\LANCommander.PCGamingWiki\LANCommander.PCGamingWiki.csproj" />
<ProjectReference Include="..\LANCommander.SDK\LANCommander.SDK.csproj" /> <ProjectReference Include="..\LANCommander.SDK\LANCommander.SDK.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,4 +1,5 @@
@model LANCommander.Models.GameViewModel @using LANCommander.Components
@model LANCommander.Models.GameViewModel
@{ @{
ViewData["Title"] = "Add Game"; ViewData["Title"] = "Add Game";
@ -83,6 +84,18 @@
</div> </div>
</div> </div>
<div class="card-header">
<h3 class="card-title">Actions</h3>
</div>
<component type="typeof(ActionEditor)" render-mode="Server" param-Actions="Model.Game.Actions" param-GameId="Model.Game.Id" />
<div class="card-header">
<h3 class="card-title">Multiplayer Modes</h3>
</div>
<component type="typeof(MultiplayerModeEditor)" render-mode="Server" param-MultiplayerModes="Model.Game.MultiplayerModes" param-GameId="Model.Game.Id" />
<div class="card-footer"> <div class="card-footer">
<div class="d-flex"> <div class="d-flex">
<a asp-action="Index" class="btn btn-ghost-primary">Cancel</a> <a asp-action="Index" class="btn btn-ghost-primary">Cancel</a>

View File

@ -0,0 +1,17 @@
using System;
namespace PCGamingWikiClient
{
private HttpClient Client;
public PCGamingWikiService()
{
Client = new HttpClient();
Client.BaseAddress = new Uri("https://www.pcgamingwiki.com/");
}
public SearchResult Search(string keyword)
{
}
}

View File

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>