forked from SoDOff-Project/sodoff
score leaderboards
This commit is contained in:
parent
879943d9e7
commit
a0e2e198da
@ -104,6 +104,7 @@ Then run School of Dragons.
|
|||||||
- GetQuestions (doesn't return all questions, probably doesn't need to)
|
- GetQuestions (doesn't return all questions, probably doesn't need to)
|
||||||
- GetRules (doesn't return any rules, probably doesn't need to)
|
- GetRules (doesn't return any rules, probably doesn't need to)
|
||||||
- GetSubscriptionInfo (always returns member, with end date 10 years from now)
|
- GetSubscriptionInfo (always returns member, with end date 10 years from now)
|
||||||
|
- SendRawGameData
|
||||||
- SetNextItemState
|
- SetNextItemState
|
||||||
- SetTaskState (only the TaskCanBeDone status is supported; might contain a serious problem - see the MissionService class)
|
- SetTaskState (only the TaskCanBeDone status is supported; might contain a serious problem - see the MissionService class)
|
||||||
- SetUserAchievementAndGetReward (works like SetAchievementAndGetReward)
|
- SetUserAchievementAndGetReward (works like SetAchievementAndGetReward)
|
||||||
@ -113,6 +114,8 @@ Then run School of Dragons.
|
|||||||
#### Partially implemented
|
#### Partially implemented
|
||||||
- ApplyPayout (doesn't calculate rewards properly)
|
- ApplyPayout (doesn't calculate rewards properly)
|
||||||
- ApplyRewards
|
- ApplyRewards
|
||||||
|
- GetGameDataByGame (friend tab displays all players - friend filter is not yet implemented because friend lists are not implemented)
|
||||||
|
- GetGameDataByGameForDateRange (friend tab displays all players)
|
||||||
- GetUserAchievements (used by Magic & Mythies)
|
- GetUserAchievements (used by Magic & Mythies)
|
||||||
- GetUserRoomList (room categories are not implemented, but it's enough for SoD)
|
- GetUserRoomList (room categories are not implemented, but it's enough for SoD)
|
||||||
- ProcessRewardedItems (gives gems, but doesn't give gold, gold is not yet implemented)
|
- ProcessRewardedItems (gives gems, but doesn't give gold, gold is not yet implemented)
|
||||||
|
@ -81,6 +81,9 @@ methods = [
|
|||||||
'ProcessRewardedItems',
|
'ProcessRewardedItems',
|
||||||
'ApplyPayout',
|
'ApplyPayout',
|
||||||
'RedeemMysteryBoxItems',
|
'RedeemMysteryBoxItems',
|
||||||
|
'SendRawGameData',
|
||||||
|
'GetGameDataByGame',
|
||||||
|
'GetGameDataByGameForDateRange',
|
||||||
]
|
]
|
||||||
|
|
||||||
def routable(path):
|
def routable(path):
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using sodoff.Attributes;
|
using sodoff.Attributes;
|
||||||
using sodoff.Model;
|
using sodoff.Model;
|
||||||
using sodoff.Schema;
|
using sodoff.Schema;
|
||||||
using sodoff.Services;
|
using sodoff.Services;
|
||||||
using sodoff.Util;
|
using sodoff.Util;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
namespace sodoff.Controllers.Common;
|
namespace sodoff.Controllers.Common;
|
||||||
public class ContentController : Controller {
|
public class ContentController : Controller {
|
||||||
@ -17,8 +17,9 @@ public class ContentController : Controller {
|
|||||||
private RoomService roomService;
|
private RoomService roomService;
|
||||||
private AchievementService achievementService;
|
private AchievementService achievementService;
|
||||||
private InventoryService inventoryService;
|
private InventoryService inventoryService;
|
||||||
|
private GameDataService gameDataService;
|
||||||
private Random random = new Random();
|
private Random random = new Random();
|
||||||
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService, InventoryService inventoryService) {
|
public ContentController(DBContext ctx, KeyValueService keyValueService, ItemService itemService, MissionService missionService, RoomService roomService, AchievementService achievementService, InventoryService inventoryService, GameDataService gameDataService) {
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.keyValueService = keyValueService;
|
this.keyValueService = keyValueService;
|
||||||
this.itemService = itemService;
|
this.itemService = itemService;
|
||||||
@ -26,6 +27,7 @@ public class ContentController : Controller {
|
|||||||
this.roomService = roomService;
|
this.roomService = roomService;
|
||||||
this.achievementService = achievementService;
|
this.achievementService = achievementService;
|
||||||
this.inventoryService = inventoryService;
|
this.inventoryService = inventoryService;
|
||||||
|
this.gameDataService = gameDataService;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
@ -1332,6 +1334,31 @@ public class ContentController : Controller {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("ContentWebService.asmx/SendRawGameData")]
|
||||||
|
[VikingSession(UseLock = true)]
|
||||||
|
public IActionResult SendRawGameData(Viking viking, [FromForm] int gameId, bool isMultiplayer, int difficulty, int gameLevel, string xmlDocumentData, bool win, bool loss) {
|
||||||
|
return Ok(gameDataService.SaveGameData(viking, gameId, isMultiplayer, difficulty, gameLevel, xmlDocumentData, win, loss));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("ContentWebService.asmx/GetGameDataByGame")]
|
||||||
|
[VikingSession(UseLock = true)]
|
||||||
|
public IActionResult GetGameDataByGame(Viking viking, [FromForm] int gameId, bool isMultiplayer, int difficulty, int gameLevel, string key, int count, bool AscendingOrder, int score, bool buddyFilter) {
|
||||||
|
return Ok(gameDataService.GetGameData(viking, gameId, isMultiplayer, difficulty, gameLevel, key, count, AscendingOrder, buddyFilter));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
[Produces("application/xml")]
|
||||||
|
[Route("V2/ContentWebService.asmx/GetGameDataByGameForDateRange")]
|
||||||
|
[VikingSession(UseLock = true)]
|
||||||
|
public IActionResult GetGameDataByGameForDateRange(Viking viking, [FromForm] int gameId, bool isMultiplayer, int difficulty, int gameLevel, string key, int count, bool AscendingOrder, int score, string startDate, string endDate, bool buddyFilter) {
|
||||||
|
CultureInfo usCulture = new CultureInfo("en-US", false);
|
||||||
|
return Ok(gameDataService.GetGameData(viking, gameId, isMultiplayer, difficulty, gameLevel, key, count, AscendingOrder, buddyFilter, DateTime.Parse(startDate, usCulture), DateTime.Parse(endDate, usCulture)));
|
||||||
|
}
|
||||||
|
|
||||||
private static RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon, int? selectedDragonId = null) {
|
private static RaisedPetData GetRaisedPetDataFromDragon (Dragon dragon, int? selectedDragonId = null) {
|
||||||
if (selectedDragonId is null)
|
if (selectedDragonId is null)
|
||||||
selectedDragonId = dragon.Viking.SelectedDragonId;
|
selectedDragonId = dragon.Viking.SelectedDragonId;
|
||||||
|
@ -14,6 +14,8 @@ public class DBContext : DbContext {
|
|||||||
public DbSet<MissionState> MissionStates { get; set; } = null!;
|
public DbSet<MissionState> MissionStates { get; set; } = null!;
|
||||||
public DbSet<Room> Rooms { get; set; } = null!;
|
public DbSet<Room> Rooms { get; set; } = null!;
|
||||||
public DbSet<RoomItem> RoomItems { get; set; } = null!;
|
public DbSet<RoomItem> RoomItems { get; set; } = null!;
|
||||||
|
public DbSet<GameData> GameData { get; set; } = null;
|
||||||
|
public DbSet<GameDataPair> GameDataPairs { get; set; } = null;
|
||||||
|
|
||||||
public string DbPath { get; }
|
public string DbPath { get; }
|
||||||
|
|
||||||
@ -79,6 +81,9 @@ public class DBContext : DbContext {
|
|||||||
.WithOne()
|
.WithOne()
|
||||||
.HasForeignKey<Viking>(e => e.SelectedDragonId);
|
.HasForeignKey<Viking>(e => e.SelectedDragonId);
|
||||||
|
|
||||||
|
builder.Entity<Viking>().HasMany(v => v.GameData)
|
||||||
|
.WithOne(e => e.Viking);
|
||||||
|
|
||||||
// Dragons
|
// Dragons
|
||||||
builder.Entity<Dragon>().HasOne(d => d.Viking)
|
builder.Entity<Dragon>().HasOne(d => d.Viking)
|
||||||
.WithMany(e => e.Dragons)
|
.WithMany(e => e.Dragons)
|
||||||
@ -134,6 +139,17 @@ public class DBContext : DbContext {
|
|||||||
.WithMany(r => r.Items)
|
.WithMany(r => r.Items)
|
||||||
.HasForeignKey(e => e.RoomId);
|
.HasForeignKey(e => e.RoomId);
|
||||||
|
|
||||||
|
// GameData
|
||||||
|
|
||||||
|
builder.Entity<GameData>().HasOne(e => e.Viking)
|
||||||
|
.WithMany(e => e.GameData);
|
||||||
|
|
||||||
|
builder.Entity<GameData>().HasMany(e => e.GameDataPairs)
|
||||||
|
.WithOne(e => e.GameData);
|
||||||
|
|
||||||
|
builder.Entity<GameDataPair>().HasOne(e => e.GameData)
|
||||||
|
.WithMany(e => e.GameDataPairs);
|
||||||
|
|
||||||
// Others ..
|
// Others ..
|
||||||
builder.Entity<Image>().HasOne(s => s.Viking)
|
builder.Entity<Image>().HasOne(s => s.Viking)
|
||||||
.WithMany(e => e.Images)
|
.WithMany(e => e.Images)
|
||||||
|
20
src/Model/GameData.cs
Normal file
20
src/Model/GameData.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace sodoff.Model;
|
||||||
|
public class GameData {
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public int VikingId { get; set; }
|
||||||
|
|
||||||
|
public int GameId { get; set; }
|
||||||
|
public int Difficulty { get; set; }
|
||||||
|
public int GameLevel { get; set; }
|
||||||
|
public DateTime DatePlayed { get; set; }
|
||||||
|
public bool IsMultiplayer { get; set; }
|
||||||
|
public bool Win { get; set; }
|
||||||
|
public bool Loss { get; set; }
|
||||||
|
public virtual ICollection<GameDataPair> GameDataPairs { get; set; } = null!;
|
||||||
|
public virtual Viking Viking { get; set; } = null!;
|
||||||
|
|
||||||
|
}
|
11
src/Model/GameDataPair.cs
Normal file
11
src/Model/GameDataPair.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace sodoff.Model;
|
||||||
|
public class GameDataPair {
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int GameDataId { get; set; }
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
public int Value { get; set; }
|
||||||
|
public virtual GameData GameData { get; set; } = null!;
|
||||||
|
}
|
@ -30,5 +30,6 @@ public class Viking {
|
|||||||
public virtual ICollection<AchievementPoints> AchievementPoints { get; set; } = null!;
|
public virtual ICollection<AchievementPoints> AchievementPoints { get; set; } = null!;
|
||||||
public virtual ICollection<PairData> PairData { get; set; } = null!;
|
public virtual ICollection<PairData> PairData { get; set; } = null!;
|
||||||
public virtual ICollection<InventoryItem> InventoryItems { get; set; } = null!;
|
public virtual ICollection<InventoryItem> InventoryItems { get; set; } = null!;
|
||||||
|
public virtual ICollection<GameData> GameData { get; set; } = null!;
|
||||||
public virtual Dragon? SelectedDragon { get; set; }
|
public virtual Dragon? SelectedDragon { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ builder.Services.AddScoped<MissionService>();
|
|||||||
builder.Services.AddScoped<RoomService>();
|
builder.Services.AddScoped<RoomService>();
|
||||||
builder.Services.AddScoped<InventoryService>();
|
builder.Services.AddScoped<InventoryService>();
|
||||||
builder.Services.AddScoped<AchievementService>();
|
builder.Services.AddScoped<AchievementService>();
|
||||||
|
builder.Services.AddScoped<GameDataService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
122
src/Services/GameDataService.cs
Normal file
122
src/Services/GameDataService.cs
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||||
|
using sodoff.Model;
|
||||||
|
using sodoff.Schema;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace sodoff.Services;
|
||||||
|
public class GameDataService {
|
||||||
|
private readonly DBContext ctx;
|
||||||
|
|
||||||
|
public GameDataService(DBContext ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SaveGameData(Viking viking, int gameId, bool isMultiplayer, int difficulty, int gameLevel, string xmlDocumentData, bool win, bool loss) {
|
||||||
|
Model.GameData? gameData = viking.GameData.FirstOrDefault(x => x.GameId == gameId && x.IsMultiplayer == isMultiplayer && x.Difficulty == difficulty && x.GameLevel == gameLevel && x.Win == win && x.Loss == loss);
|
||||||
|
if (gameData == null) {
|
||||||
|
gameData = new Model.GameData {
|
||||||
|
GameId = gameId,
|
||||||
|
IsMultiplayer = isMultiplayer,
|
||||||
|
Difficulty = difficulty,
|
||||||
|
GameLevel = gameLevel,
|
||||||
|
Win = win,
|
||||||
|
Loss = loss,
|
||||||
|
GameDataPairs = new List<GameDataPair>()
|
||||||
|
};
|
||||||
|
viking.GameData.Add(gameData);
|
||||||
|
|
||||||
|
}
|
||||||
|
gameData.DatePlayed = DateTime.Now;
|
||||||
|
SavePairs(gameData, xmlDocumentData);
|
||||||
|
ctx.SaveChanges();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameDataSummary GetGameData(Viking viking, [FromForm] int gameId, bool isMultiplayer, int difficulty, int gameLevel, string key, int count, bool AscendingOrder, bool buddyFilter, DateTime? startDate = null, DateTime? endDate = null) {
|
||||||
|
// TODO: Buddy filter
|
||||||
|
List<GameDataResponse> selectedData;
|
||||||
|
IQueryable<Model.GameData> query = ctx.GameData.Where(x => x.GameId == gameId && x.IsMultiplayer == false && x.Difficulty == difficulty && x.GameLevel == gameLevel);
|
||||||
|
|
||||||
|
if (startDate != null && endDate != null)
|
||||||
|
query = query.Where(x => x.DatePlayed >= startDate && x.DatePlayed <= endDate.Value.AddMinutes(2));
|
||||||
|
|
||||||
|
selectedData = query.SelectMany(e => e.GameDataPairs)
|
||||||
|
.Where(x => x.Name == key)
|
||||||
|
.Select(e => new GameDataResponse(e.GameData.Viking.Name, e.GameData.Viking.Uid, e.GameData.DatePlayed, e.GameData.Win, e.GameData.Loss, e.Value))
|
||||||
|
.Take(count)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (AscendingOrder)
|
||||||
|
selectedData.Sort((a, b) => a.Value.CompareTo(b.Value));
|
||||||
|
else
|
||||||
|
selectedData.Sort((a, b) => b.Value.CompareTo(a.Value));
|
||||||
|
|
||||||
|
return GetSummaryFromResponse(viking, isMultiplayer, difficulty, gameLevel, key, selectedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameDataSummary GetSummaryFromResponse(Viking viking, bool isMultiplayer, int difficulty, int gameLevel, string key, List<GameDataResponse> selectedData) {
|
||||||
|
GameDataSummary gameData = new();
|
||||||
|
gameData.IsMultiplayer = isMultiplayer;
|
||||||
|
gameData.Difficulty = difficulty;
|
||||||
|
gameData.GameLevel = gameLevel;
|
||||||
|
gameData.Key = key;
|
||||||
|
gameData.UserPosition = -1;
|
||||||
|
gameData.GameDataList = new Schema.GameData[selectedData.Count];
|
||||||
|
for (int i = 0; i < selectedData.Count; i++) {
|
||||||
|
Schema.GameData data = new();
|
||||||
|
data.RankID = i + 1;
|
||||||
|
data.IsMember = true;
|
||||||
|
data.UserName = selectedData[i].Name;
|
||||||
|
data.Value = selectedData[i].Value;
|
||||||
|
data.DatePlayed = selectedData[i].DatePlayed;
|
||||||
|
data.Win = selectedData[i].Win ? 1 : 0;
|
||||||
|
data.Loss = selectedData[i].Loss ? 1 : 0;
|
||||||
|
data.UserID = selectedData[i].Uid;
|
||||||
|
gameData.GameDataList[i] = data;
|
||||||
|
if (data.UserName == viking.Name && gameData.UserPosition == -1)
|
||||||
|
gameData.UserPosition = i;
|
||||||
|
}
|
||||||
|
if (gameData.UserPosition == -1)
|
||||||
|
gameData.UserPosition = selectedData.Count;
|
||||||
|
return gameData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SavePairs(Model.GameData gameData, string xmlDocumentData) {
|
||||||
|
foreach (var pair in GetGameDataPairs(xmlDocumentData)) {
|
||||||
|
GameDataPair? dbPair = gameData.GameDataPairs.FirstOrDefault(x => x.Name == pair.Name);
|
||||||
|
if (dbPair == null)
|
||||||
|
gameData.GameDataPairs.Add(pair);
|
||||||
|
else
|
||||||
|
dbPair.Value = pair.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ICollection<GameDataPair> GetGameDataPairs(string xmlDocumentData) {
|
||||||
|
List<GameDataPair> pairs = new();
|
||||||
|
foreach (Match match in Regex.Matches(xmlDocumentData, @"<(\w+)>(.*?)<\/\1>")) {
|
||||||
|
pairs.Add(new GameDataPair {
|
||||||
|
Name = match.Groups[1].Value,
|
||||||
|
Value = int.Parse(match.Groups[2].Value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return pairs;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GameDataResponse {
|
||||||
|
public GameDataResponse(string Name, Guid Uid, DateTime DatePlayed, bool Win, bool Loss, int Value) {
|
||||||
|
this.Name = Name;
|
||||||
|
this.Uid = Uid;
|
||||||
|
this.DatePlayed = DatePlayed;
|
||||||
|
this.Win = Win;
|
||||||
|
this.Loss = Loss;
|
||||||
|
this.Value = Value;
|
||||||
|
}
|
||||||
|
public string Name;
|
||||||
|
public Guid Uid;
|
||||||
|
public DateTime DatePlayed;
|
||||||
|
public bool Win;
|
||||||
|
public bool Loss;
|
||||||
|
public int Value;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user