Add more filter types (#50)
* feat: support for filtering by igdb rating * fix: new user rating filter was always excluding unrated games * feat: added metadata for game multiplayer modes * feat: added metadata for game player perspectives * feat: added metadata for game themes * chore(deps): EmulatorJS version bump * feat: all filters added * feat: filter options now have visible toggles * feat: jazzed up the styling of the game rating
This commit is contained in:
110
gaseous-server/Classes/Metadata/GameModes.cs
Normal file
110
gaseous-server/Classes/Metadata/GameModes.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class GameModes
|
||||
{
|
||||
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
|
||||
|
||||
public GameModes()
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static GameMode? GetGame_Modes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static GameMode GetGame_Modes(string Slug)
|
||||
{
|
||||
Task<GameMode> RetVal = _GetGame_Modes(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<GameMode> _GetGame_Modes(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("GameMode", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("GameMode", (string)searchValue);
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
}
|
||||
|
||||
GameMode returnValue = new GameMode();
|
||||
bool forceImageDownload = false;
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<GameMode>(returnValue, "id", (long)searchValue);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<GameMode> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_Modes metadata
|
||||
var results = await igdb.QueryAsync<GameMode>(IGDBClient.Endpoints.GameModes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -205,6 +205,22 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.GameModes != null)
|
||||
{
|
||||
foreach (long gameModeId in Game.GameModes.Ids)
|
||||
{
|
||||
GameMode gameMode = GameModes.GetGame_Modes(gameModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.MultiplayerModes != null)
|
||||
{
|
||||
foreach (long multiplayerModeId in Game.MultiplayerModes.Ids)
|
||||
{
|
||||
MultiplayerMode multiplayerMode = MultiplayerModes.GetGame_MultiplayerModes(multiplayerModeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Platforms != null)
|
||||
{
|
||||
foreach (long PlatformId in Game.Platforms.Ids)
|
||||
@@ -213,6 +229,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.PlayerPerspectives != null)
|
||||
{
|
||||
foreach (long PerspectiveId in Game.PlayerPerspectives.Ids)
|
||||
{
|
||||
PlayerPerspective GamePlayPerspective = PlayerPerspectives.GetGame_PlayerPerspectives(PerspectiveId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Screenshots != null)
|
||||
{
|
||||
foreach (long ScreenshotId in Game.Screenshots.Ids)
|
||||
@@ -221,6 +245,14 @@ namespace gaseous_server.Classes.Metadata
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Themes != null)
|
||||
{
|
||||
foreach (long ThemeId in Game.Themes.Ids)
|
||||
{
|
||||
Theme GameTheme = Themes.GetGame_Themes(ThemeId);
|
||||
}
|
||||
}
|
||||
|
||||
if (Game.Videos != null)
|
||||
{
|
||||
foreach (long GameVideoId in Game.Videos.Ids)
|
||||
|
110
gaseous-server/Classes/Metadata/MultiplayerModes.cs
Normal file
110
gaseous-server/Classes/Metadata/MultiplayerModes.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class MultiplayerModes
|
||||
{
|
||||
const string fieldList = "fields campaigncoop,checksum,dropin,game,lancoop,offlinecoop,offlinecoopmax,offlinemax,onlinecoop,onlinecoopmax,onlinemax,platform,splitscreen,splitscreenonline;";
|
||||
|
||||
public MultiplayerModes()
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static MultiplayerMode? GetGame_MultiplayerModes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static MultiplayerMode GetGame_MultiplayerModes(string Slug)
|
||||
{
|
||||
Task<MultiplayerMode> RetVal = _GetGame_MultiplayerModes(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<MultiplayerMode> _GetGame_MultiplayerModes(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("MultiplayerMode", (string)searchValue);
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
}
|
||||
|
||||
MultiplayerMode returnValue = new MultiplayerMode();
|
||||
bool forceImageDownload = false;
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<MultiplayerMode>(returnValue, "id", (long)searchValue);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<MultiplayerMode> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_MultiplayerModes metadata
|
||||
var results = await igdb.QueryAsync<MultiplayerMode>(IGDBClient.Endpoints.MultiplayerModes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
gaseous-server/Classes/Metadata/PlayerPerspectives.cs
Normal file
110
gaseous-server/Classes/Metadata/PlayerPerspectives.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class PlayerPerspectives
|
||||
{
|
||||
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
|
||||
|
||||
public PlayerPerspectives()
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static PlayerPerspective? GetGame_PlayerPerspectives(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static PlayerPerspective GetGame_PlayerPerspectives(string Slug)
|
||||
{
|
||||
Task<PlayerPerspective> RetVal = _GetGame_PlayerPerspectives(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<PlayerPerspective> _GetGame_PlayerPerspectives(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("PlayerPerspective", (string)searchValue);
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
}
|
||||
|
||||
PlayerPerspective returnValue = new PlayerPerspective();
|
||||
bool forceImageDownload = false;
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<PlayerPerspective>(returnValue, "id", (long)searchValue);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<PlayerPerspective> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_PlayerPerspectives metadata
|
||||
var results = await igdb.QueryAsync<PlayerPerspective>(IGDBClient.Endpoints.PlayerPerspectives, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
110
gaseous-server/Classes/Metadata/Themes.cs
Normal file
110
gaseous-server/Classes/Metadata/Themes.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using gaseous_tools;
|
||||
using IGDB;
|
||||
using IGDB.Models;
|
||||
using MySqlX.XDevAPI.Common;
|
||||
using static gaseous_tools.Config.ConfigFile;
|
||||
|
||||
namespace gaseous_server.Classes.Metadata
|
||||
{
|
||||
public class Themes
|
||||
{
|
||||
const string fieldList = "fields checksum,created_at,name,slug,updated_at,url;";
|
||||
|
||||
public Themes()
|
||||
{
|
||||
}
|
||||
|
||||
private static IGDBClient igdb = new IGDBClient(
|
||||
// Found in Twitch Developer portal for your app
|
||||
Config.IGDB.ClientId,
|
||||
Config.IGDB.Secret
|
||||
);
|
||||
|
||||
public static Theme? GetGame_Themes(long? Id)
|
||||
{
|
||||
if ((Id == 0) || (Id == null))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.id, Id);
|
||||
return RetVal.Result;
|
||||
}
|
||||
}
|
||||
|
||||
public static Theme GetGame_Themes(string Slug)
|
||||
{
|
||||
Task<Theme> RetVal = _GetGame_Themes(SearchUsing.slug, Slug);
|
||||
return RetVal.Result;
|
||||
}
|
||||
|
||||
private static async Task<Theme> _GetGame_Themes(SearchUsing searchUsing, object searchValue)
|
||||
{
|
||||
// check database first
|
||||
Storage.CacheStatus? cacheStatus = new Storage.CacheStatus();
|
||||
if (searchUsing == SearchUsing.id)
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("Theme", (long)searchValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStatus = Storage.GetCacheStatus("Theme", (string)searchValue);
|
||||
}
|
||||
|
||||
// set up where clause
|
||||
string WhereClause = "";
|
||||
switch (searchUsing)
|
||||
{
|
||||
case SearchUsing.id:
|
||||
WhereClause = "where id = " + searchValue;
|
||||
break;
|
||||
case SearchUsing.slug:
|
||||
WhereClause = "where slug = " + searchValue;
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid search type");
|
||||
}
|
||||
|
||||
Theme returnValue = new Theme();
|
||||
bool forceImageDownload = false;
|
||||
switch (cacheStatus)
|
||||
{
|
||||
case Storage.CacheStatus.NotPresent:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Expired:
|
||||
returnValue = await GetObjectFromServer(WhereClause);
|
||||
Storage.NewCacheValue(returnValue, true);
|
||||
forceImageDownload = true;
|
||||
break;
|
||||
case Storage.CacheStatus.Current:
|
||||
returnValue = Storage.GetCacheValue<Theme>(returnValue, "id", (long)searchValue);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("How did you get here?");
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
private enum SearchUsing
|
||||
{
|
||||
id,
|
||||
slug
|
||||
}
|
||||
|
||||
private static async Task<Theme> GetObjectFromServer(string WhereClause)
|
||||
{
|
||||
// get Game_Themes metadata
|
||||
var results = await igdb.QueryAsync<Theme>(IGDBClient.Endpoints.Themes, query: fieldList + " " + WhereClause + ";");
|
||||
var result = results.First();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,39 @@ namespace gaseous_server.Controllers
|
||||
}
|
||||
FilterSet.Add("genres", genres);
|
||||
|
||||
// game modes
|
||||
List<GameMode> gameModes = new List<GameMode>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM GameMode AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.GameModes, CAST(t1.Id AS char), '$') ORDER BY t1.Id";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
gameModes.Add(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("gamemodes", gameModes);
|
||||
|
||||
// player perspectives
|
||||
List<PlayerPerspective> playerPerspectives = new List<PlayerPerspective>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM PlayerPerspective AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.PlayerPerspectives, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
playerPerspectives.Add(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("playerperspectives", playerPerspectives);
|
||||
|
||||
// themes
|
||||
List<Theme> themes = new List<Theme>();
|
||||
sql = "SELECT DISTINCT t1.Id, t1.`Name` FROM Theme AS t1 JOIN (SELECT * FROM Game WHERE (SELECT COUNT(Id) FROM Games_Roms WHERE GameId = Game.Id) > 0) AS t2 ON JSON_CONTAINS(t2.Themes, CAST(t1.Id AS char), '$') ORDER BY t1.`Name`";
|
||||
dbResponse = db.ExecuteCMD(sql);
|
||||
|
||||
foreach (DataRow dr in dbResponse.Rows)
|
||||
{
|
||||
themes.Add(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"]));
|
||||
}
|
||||
FilterSet.Add("themes", themes);
|
||||
|
||||
return FilterSet;
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,16 @@ namespace gaseous_server.Controllers
|
||||
{
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<Game>), StatusCodes.Status200OK)]
|
||||
public ActionResult Game(string name = "", string platform = "", string genre = "", bool sortdescending = false)
|
||||
public ActionResult Game(
|
||||
string name = "",
|
||||
string platform = "",
|
||||
string genre = "",
|
||||
string gamemode = "",
|
||||
string playerperspective = "",
|
||||
string theme = "",
|
||||
int minrating = -1,
|
||||
int maxrating = -1,
|
||||
bool sortdescending = false)
|
||||
{
|
||||
string whereClause = "";
|
||||
string havingClause = "";
|
||||
@@ -41,6 +50,20 @@ namespace gaseous_server.Controllers
|
||||
havingClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (minrating != -1)
|
||||
{
|
||||
string ratingTempMinVal = "totalRating >= @totalMinRating";
|
||||
whereParams.Add("@totalMinRating", minrating);
|
||||
havingClauses.Add(ratingTempMinVal);
|
||||
}
|
||||
|
||||
if (maxrating != -1)
|
||||
{
|
||||
string ratingTempMaxVal = "totalRating <= @totalMaxRating";
|
||||
whereParams.Add("@totalMaxRating", maxrating);
|
||||
havingClauses.Add(ratingTempMaxVal);
|
||||
}
|
||||
|
||||
if (platform.Length > 0)
|
||||
{
|
||||
tempVal = "Games_Roms.PlatformId IN (";
|
||||
@@ -77,6 +100,60 @@ namespace gaseous_server.Controllers
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (gamemode.Length > 0)
|
||||
{
|
||||
tempVal = "(";
|
||||
string[] gameModeClauseItems = gamemode.Split(",");
|
||||
for (int i = 0; i < gameModeClauseItems.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string gameModeLabel = "@GameMode" + i;
|
||||
tempVal += "JSON_CONTAINS(Game.GameModes, " + gameModeLabel + ", '$')";
|
||||
whereParams.Add(gameModeLabel, gameModeClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (playerperspective.Length > 0)
|
||||
{
|
||||
tempVal = "(";
|
||||
string[] playerPerspectiveClauseItems = playerperspective.Split(",");
|
||||
for (int i = 0; i < playerPerspectiveClauseItems.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string playerPerspectiveLabel = "@PlayerPerspective" + i;
|
||||
tempVal += "JSON_CONTAINS(Game.PlayerPerspectives, " + playerPerspectiveLabel + ", '$')";
|
||||
whereParams.Add(playerPerspectiveLabel, playerPerspectiveClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
if (theme.Length > 0)
|
||||
{
|
||||
tempVal = "(";
|
||||
string[] themeClauseItems = theme.Split(",");
|
||||
for (int i = 0; i < themeClauseItems.Length; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
tempVal += " AND ";
|
||||
}
|
||||
string themeLabel = "@Theme" + i;
|
||||
tempVal += "JSON_CONTAINS(Game.Themes, " + themeLabel + ", '$')";
|
||||
whereParams.Add(themeLabel, themeClauseItems[i]);
|
||||
}
|
||||
tempVal += ")";
|
||||
whereClauses.Add(tempVal);
|
||||
}
|
||||
|
||||
// build where clause
|
||||
if (whereClauses.Count > 0)
|
||||
{
|
||||
|
Submodule gaseous-server/wwwroot/emulators/EmulatorJS updated: e19c0233d1...8c5def77a0
@@ -4,11 +4,17 @@
|
||||
|
||||
<div id="gamepage">
|
||||
<div id="gametitle">
|
||||
<div id="gametitle_criticrating">
|
||||
<span id="gametitle_criticrating_value"></span>
|
||||
<span id="gametitle_criticrating_label"></span>
|
||||
</div>
|
||||
<h1 id="gametitle_label"></h1>
|
||||
<p id="gamedeveloper_label"></p>
|
||||
|
||||
<p id="gametitle_alts">
|
||||
<span>Also known as: </span><span id="gametitle_alts_label"></span>
|
||||
</p>
|
||||
|
||||
<p id="gamedeveloper_label"></p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -78,6 +84,17 @@
|
||||
var gameTitleLabel = document.getElementById('gametitle_label');
|
||||
gameTitleLabel.innerHTML = result.name;
|
||||
|
||||
// get critic rating
|
||||
if (gameData.totalRating) {
|
||||
var criticscoreval = document.getElementById('gametitle_criticrating_value');
|
||||
criticscoreval.innerHTML = Math.floor(gameData.totalRating) + '%';
|
||||
|
||||
if (gameData.totalRatingCount) {
|
||||
var criticscorelabel = document.getElementById('gametitle_criticrating_label');
|
||||
criticscorelabel.innerHTML = "based on <br />" + gameData.totalRatingCount + " votes"
|
||||
}
|
||||
}
|
||||
|
||||
// get alt name
|
||||
var gameTitleAltLabel = document.getElementById('gametitle_alts');
|
||||
if (result.alternativeNames) {
|
||||
|
@@ -7,10 +7,12 @@
|
||||
ajaxCall('/api/v1/Filter', 'GET', function (result) {
|
||||
var filterElement = document.getElementById('games_filter');
|
||||
formatFilterPanel(filterElement, result);
|
||||
|
||||
executeFilter();
|
||||
});
|
||||
|
||||
ajaxCall('/api/v1/Games', 'GET', function (result) {
|
||||
var gameElement = document.getElementById('games_library');
|
||||
formatGamesPanel(gameElement, result);
|
||||
});
|
||||
//ajaxCall('/api/v1/Games', 'GET', function (result) {
|
||||
// var gameElement = document.getElementById('games_library');
|
||||
// formatGamesPanel(gameElement, result);
|
||||
//});
|
||||
</script>
|
@@ -15,44 +15,111 @@
|
||||
|
||||
panel.appendChild(containerPanelSearch);
|
||||
|
||||
panel.appendChild(buildFilterPanelHeader('userrating', 'User Rating'));
|
||||
var containerPanelUserRating = document.createElement('div');
|
||||
containerPanelUserRating.className = 'filter_panel_box';
|
||||
var containerPanelUserRatingMinField = document.createElement('input');
|
||||
containerPanelUserRatingMinField.id = 'filter_panel_userrating_min';
|
||||
containerPanelUserRatingMinField.type = 'number';
|
||||
containerPanelUserRatingMinField.placeholder = '0';
|
||||
containerPanelUserRatingMinField.setAttribute('onchange', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMinField.setAttribute('onkeydown', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMinField.setAttribute('min', '0');
|
||||
containerPanelUserRatingMinField.setAttribute('max', '100');
|
||||
containerPanelUserRating.appendChild(containerPanelUserRatingMinField);
|
||||
|
||||
var containerPanelUserRatingMaxField = document.createElement('input');
|
||||
containerPanelUserRatingMaxField.id = 'filter_panel_userrating_max';
|
||||
containerPanelUserRatingMaxField.type = 'number';
|
||||
containerPanelUserRatingMaxField.placeholder = '100';
|
||||
containerPanelUserRatingMaxField.setAttribute('onchange', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMaxField.setAttribute('onkeydown', 'executeFilterDelayed();');
|
||||
containerPanelUserRatingMaxField.setAttribute('min', '0');
|
||||
containerPanelUserRatingMaxField.setAttribute('max', '100');
|
||||
containerPanelUserRating.appendChild(containerPanelUserRatingMaxField);
|
||||
|
||||
panel.appendChild(containerPanelUserRating);
|
||||
|
||||
if (result.platforms) {
|
||||
panel.appendChild(buildFilterPanelHeader('platforms', 'Platforms'));
|
||||
|
||||
var containerPanelPlatform = document.createElement('div');
|
||||
containerPanelPlatform.className = 'filter_panel_box';
|
||||
for (var i = 0; i < result.platforms.length; i++) {
|
||||
containerPanelPlatform.appendChild(buildFilterPanelItem('platforms', result.platforms[i].id, result.platforms[i].name));
|
||||
}
|
||||
panel.appendChild(containerPanelPlatform);
|
||||
|
||||
targetElement.appendChild(panel);
|
||||
buildFilterPanel(panel, 'platform', 'Platforms', result.platforms, true, true);
|
||||
}
|
||||
|
||||
if (result.genres) {
|
||||
panel.appendChild(buildFilterPanelHeader('genres', 'Genres'));
|
||||
|
||||
var containerPanelGenres = document.createElement('div');
|
||||
containerPanelGenres.className = 'filter_panel_box';
|
||||
for (var i = 0; i < result.genres.length; i++) {
|
||||
containerPanelGenres.appendChild(buildFilterPanelItem('genres', result.genres[i].id, result.genres[i].name));
|
||||
}
|
||||
panel.appendChild(containerPanelGenres);
|
||||
|
||||
targetElement.appendChild(panel);
|
||||
buildFilterPanel(panel, 'genre', 'Genres', result.genres, true, false);
|
||||
}
|
||||
|
||||
|
||||
if (result.gamemodes) {
|
||||
buildFilterPanel(panel, 'gamemode', 'Players', result.gamemodes, true, false);
|
||||
}
|
||||
|
||||
if (result.playerperspectives) {
|
||||
buildFilterPanel(panel, 'playerperspective', 'Player Perspectives', result.playerperspectives, true, false);
|
||||
}
|
||||
|
||||
if (result.themes) {
|
||||
buildFilterPanel(panel, 'theme', 'Themes', result.themes, true, false);
|
||||
}
|
||||
|
||||
targetElement.appendChild(panel);
|
||||
}
|
||||
|
||||
function buildFilterPanelHeader(headerString, friendlyHeaderString) {
|
||||
function buildFilterPanel(targetElement, headerString, friendlyHeaderString, valueList, showToggle, initialDisplay) {
|
||||
if (showToggle == false) { initialDisplay = true; }
|
||||
targetElement.appendChild(buildFilterPanelHeader(headerString, friendlyHeaderString, showToggle, initialDisplay));
|
||||
|
||||
var containerPanel = document.createElement('div');
|
||||
containerPanel.className = 'filter_panel_box';
|
||||
containerPanel.id = 'filter_panel_box_' + headerString;
|
||||
if (initialDisplay == false) {
|
||||
containerPanel.setAttribute('style', 'display: none;');
|
||||
}
|
||||
for (var i = 0; i < valueList.length; i++) {
|
||||
containerPanel.appendChild(buildFilterPanelItem(headerString, valueList[i].id, valueList[i].name));
|
||||
}
|
||||
targetElement.appendChild(containerPanel);
|
||||
}
|
||||
|
||||
function buildFilterPanelHeader(headerString, friendlyHeaderString, showVisibleToggle, toggleInitialValue) {
|
||||
var headerToggle = document.createElement('div');
|
||||
headerToggle.setAttribute('style', 'float: right;');
|
||||
headerToggle.id = 'filter_panel_header_toggle_' + headerString;
|
||||
if (toggleInitialValue == true) {
|
||||
headerToggle.innerHTML = '-';
|
||||
} else {
|
||||
headerToggle.innerHTML = '+';
|
||||
}
|
||||
|
||||
var headerLabel = document.createElement('span');
|
||||
headerLabel.innerHTML = friendlyHeaderString;
|
||||
|
||||
var header = document.createElement('div');
|
||||
header.id = 'filter_panel_header_' + headerString;
|
||||
header.className = 'filter_header';
|
||||
header.innerHTML = friendlyHeaderString;
|
||||
|
||||
if (showVisibleToggle == true) {
|
||||
header.appendChild(headerToggle);
|
||||
header.setAttribute('onclick', 'toggleFilterPanel("' + headerString + '");');
|
||||
header.style.cursor = 'pointer';
|
||||
}
|
||||
|
||||
header.appendChild(headerLabel);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
function toggleFilterPanel(panelName) {
|
||||
var filterPanel = document.getElementById('filter_panel_box_' + panelName);
|
||||
var filterPanelToggle = document.getElementById('filter_panel_header_toggle_' + panelName);
|
||||
|
||||
if (filterPanel.style.display == 'none') {
|
||||
filterPanelToggle.innerHTML = '-';
|
||||
filterPanel.style.display = '';
|
||||
} else {
|
||||
filterPanelToggle.innerHTML = '+';
|
||||
filterPanel.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
|
||||
var filterPanelItem = document.createElement('div');
|
||||
filterPanelItem.id = 'filter_panel_item_' + itemString;
|
||||
@@ -61,7 +128,7 @@ function buildFilterPanelItem(filterType, itemString, friendlyItemString) {
|
||||
var filterPanelItemCheckBox = document.createElement('div');
|
||||
|
||||
var filterPanelItemCheckBoxItem = document.createElement('input');
|
||||
filterPanelItemCheckBoxItem.id = 'filter_panel_item_checkbox_' + itemString;
|
||||
filterPanelItemCheckBoxItem.id = 'filter_panel_item_' + filterType + '_checkbox_' + itemString;
|
||||
filterPanelItemCheckBoxItem.type = 'checkbox';
|
||||
filterPanelItemCheckBoxItem.className = 'filter_panel_item_checkbox';
|
||||
filterPanelItemCheckBoxItem.name = 'filter_' + filterType;
|
||||
@@ -92,33 +159,73 @@ function executeFilterDelayed() {
|
||||
|
||||
function executeFilter() {
|
||||
// build filter lists
|
||||
var queries = [];
|
||||
|
||||
var platforms = '';
|
||||
var genres = '';
|
||||
|
||||
var searchString = document.getElementById('filter_panel_search').value;
|
||||
var platformFilters = document.getElementsByName('filter_platforms');
|
||||
var genreFilters = document.getElementsByName('filter_genres');
|
||||
if (searchString.length > 0) {
|
||||
queries.push('name=' + searchString);
|
||||
}
|
||||
|
||||
for (var i = 0; i < platformFilters.length; i++) {
|
||||
if (platformFilters[i].checked) {
|
||||
if (platforms.length > 0) {
|
||||
platforms += ',';
|
||||
var minUserRating = 0;
|
||||
var minUserRatingInput = document.getElementById('filter_panel_userrating_min').value;
|
||||
if (minUserRatingInput) {
|
||||
minUserRating = minUserRatingInput;
|
||||
queries.push('minrating=' + minUserRating);
|
||||
}
|
||||
|
||||
var maxUserRating = 100;
|
||||
var maxUserRatingInput = document.getElementById('filter_panel_userrating_max').value;
|
||||
if (maxUserRatingInput) {
|
||||
maxUserRating = maxUserRatingInput;
|
||||
queries.push('maxrating=' + maxUserRating);
|
||||
}
|
||||
|
||||
queries.push(GetFilterQuery('platform'));
|
||||
queries.push(GetFilterQuery('genre'));
|
||||
queries.push(GetFilterQuery('gamemode'));
|
||||
queries.push(GetFilterQuery('playerperspective'));
|
||||
queries.push(GetFilterQuery('theme'));
|
||||
|
||||
var queryString = '';
|
||||
for (var i = 0; i < queries.length; i++) {
|
||||
if (queries[i].length > 0) {
|
||||
if (queryString.length == 0) {
|
||||
queryString = '?';
|
||||
} else {
|
||||
queryString += '&';
|
||||
}
|
||||
platforms += platformFilters[i].getAttribute('filter_id');
|
||||
|
||||
queryString += queries[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < genreFilters.length; i++) {
|
||||
if (genreFilters[i].checked) {
|
||||
if (genres.length > 0) {
|
||||
genres += ',';
|
||||
}
|
||||
genres += genreFilters[i].getAttribute('filter_id');
|
||||
}
|
||||
}
|
||||
console.log('Query string = ' + queryString);
|
||||
|
||||
ajaxCall('/api/v1/Games?name=' + searchString + '&platform=' + platforms + '&genre=' + genres, 'GET', function (result) {
|
||||
ajaxCall('/api/v1/Games' + queryString, 'GET', function (result) {
|
||||
var gameElement = document.getElementById('games_library');
|
||||
formatGamesPanel(gameElement, result);
|
||||
});
|
||||
}
|
||||
|
||||
function GetFilterQuery(filterName) {
|
||||
var Filters = document.getElementsByName('filter_' + filterName);
|
||||
var queryString = '';
|
||||
|
||||
for (var i = 0; i < Filters.length; i++) {
|
||||
if (Filters[i].checked) {
|
||||
if (queryString.length > 0) {
|
||||
queryString += ',';
|
||||
}
|
||||
queryString += Filters[i].getAttribute('filter_id');
|
||||
}
|
||||
}
|
||||
|
||||
if (queryString.length > 0) {
|
||||
queryString = filterName + '=' + queryString;
|
||||
}
|
||||
|
||||
return queryString;
|
||||
}
|
@@ -13,6 +13,10 @@
|
||||
src: url('/fonts/Commodore Pixelized v1.2.ttf');
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: unset;
|
||||
}
|
||||
|
||||
h3 {
|
||||
border-bottom-style: solid;
|
||||
/*border-bottom-color: #916b01;*/
|
||||
@@ -206,7 +210,7 @@ h3 {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
input[type='text'] {
|
||||
input[type='text'], input[type='number'] {
|
||||
background-color: #2b2b2b;
|
||||
color: white;
|
||||
padding: 5px;
|
||||
@@ -225,6 +229,15 @@ input[id='filter_panel_search'] {
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
input[id='filter_panel_userrating_min'] {
|
||||
width: 50px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
input[id='filter_panel_userrating_max'] {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
/* width */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
@@ -286,12 +299,20 @@ input[id='filter_panel_search'] {
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
-webkit-border-radius: 10px 10px 10px 10px;
|
||||
-moz-border-radius: 10px 10px 10px 10px;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.game_tile:hover {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 10px 10px 10px 10px;
|
||||
-webkit-border-radius: 10px 10px 10px 10px;
|
||||
-moz-border-radius: 10px 10px 10px 10px;
|
||||
border: 1px solid #2b2b2b;
|
||||
}
|
||||
|
||||
.game_tile_image {
|
||||
@@ -770,4 +791,25 @@ button:disabled {
|
||||
box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-webkit-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
-moz-box-shadow: 5px 5px 19px 0px rgba(0,0,0,0.44);
|
||||
}
|
||||
|
||||
#gametitle_criticrating {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#gametitle_alts {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
#gametitle_criticrating_value {
|
||||
display: inline-block;
|
||||
font-family: Commodore64;
|
||||
font-size: 36px;
|
||||
text-align: center;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#gametitle_criticrating_label {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
65
gaseous-tools/Database/MySQL/gaseous-1001.sql
Normal file
65
gaseous-tools/Database/MySQL/gaseous-1001.sql
Normal file
@@ -0,0 +1,65 @@
|
||||
DROP TABLE IF EXISTS `GameMode`;
|
||||
CREATE TABLE `gaseous`.`GameMode` (
|
||||
`Id` BIGINT NOT NULL,
|
||||
`CreatedAt` DATETIME NULL,
|
||||
`Checksum` VARCHAR(45) NULL,
|
||||
`Name` VARCHAR(100) NULL,
|
||||
`Slug` VARCHAR(100) NULL,
|
||||
`UpdatedAt` DATETIME NULL,
|
||||
`Url` VARCHAR(255) NULL,
|
||||
`dateAdded` DATETIME NULL,
|
||||
`lastUpdated` DATETIME NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `MultiplayerMode`;
|
||||
CREATE TABLE `MultiplayerMode` (
|
||||
`Id` bigint NOT NULL,
|
||||
`CreatedAt` datetime DEFAULT NULL,
|
||||
`Checksum` varchar(45) DEFAULT NULL,
|
||||
`CampaignCoop` boolean DEFAULT NULL,
|
||||
`DropIn` boolean DEFAULT NULL,
|
||||
`Game` bigint DEFAULT NULL,
|
||||
`LanCoop` boolean DEFAULT NULL,
|
||||
`OfflineCoop` boolean DEFAULT NULL,
|
||||
`OfflineCoopMax` int DEFAULT NULL,
|
||||
`OfflineMax` int DEFAULT NULL,
|
||||
`OnlineCoop` boolean DEFAULT NULL,
|
||||
`OnlineCoopMax` int DEFAULT NULL,
|
||||
`OnlineMax` int DEFAULT NULL,
|
||||
`Platform` bigint DEFAULT NULL,
|
||||
`SplitScreen` boolean DEFAULT NULL,
|
||||
`SplitScreenOnline` boolean DEFAULT NULL,
|
||||
`UpdatedAt` datetime DEFAULT NULL,
|
||||
`dateAdded` datetime DEFAULT NULL,
|
||||
`lastUpdated` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `PlayerPerspective`;
|
||||
CREATE TABLE `PlayerPerspective` (
|
||||
`Id` bigint NOT NULL,
|
||||
`CreatedAt` datetime DEFAULT NULL,
|
||||
`Checksum` varchar(45) DEFAULT NULL,
|
||||
`Name` varchar(100) DEFAULT NULL,
|
||||
`Slug` varchar(45) DEFAULT NULL,
|
||||
`UpdatedAt` datetime DEFAULT NULL,
|
||||
`Url` varchar(255) DEFAULT NULL,
|
||||
`dateAdded` datetime DEFAULT NULL,
|
||||
`lastUpdated` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `Theme`;
|
||||
CREATE TABLE `Theme` (
|
||||
`Id` bigint NOT NULL,
|
||||
`CreatedAt` datetime DEFAULT NULL,
|
||||
`Checksum` varchar(45) DEFAULT NULL,
|
||||
`Name` varchar(100) DEFAULT NULL,
|
||||
`Slug` varchar(45) DEFAULT NULL,
|
||||
`UpdatedAt` datetime DEFAULT NULL,
|
||||
`Url` varchar(255) DEFAULT NULL,
|
||||
`dateAdded` datetime DEFAULT NULL,
|
||||
`lastUpdated` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`Id`)
|
||||
);
|
@@ -16,6 +16,7 @@
|
||||
<None Remove="Database\" />
|
||||
<None Remove="Database\MySQL\" />
|
||||
<None Remove="Database\MySQL\gaseous-1000.sql" />
|
||||
<None Remove="Database\MySQL\gaseous-1001.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Database\" />
|
||||
@@ -23,5 +24,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Database\MySQL\gaseous-1000.sql" />
|
||||
<EmbeddedResource Include="Database\MySQL\gaseous-1001.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Reference in New Issue
Block a user