Change Db Structure & Add OnlyPlayOnce & Add CompeteState & Compete Option can be null
This commit is contained in:
parent
e545598c1c
commit
d755d6edd5
@ -6,6 +6,7 @@ public partial class ChallengeCompeteDatum
|
||||
{
|
||||
public uint CompId { get; set; }
|
||||
public CompeteModeType CompeteMode { get; set; } = CompeteModeType.None;
|
||||
public CompeteState State { get; set; } = CompeteState.Normal;
|
||||
public uint Baid { get; set; }
|
||||
public string CompeteName { get; set; } = String.Empty;
|
||||
public string CompeteDescribe { get; set; } = String.Empty;
|
||||
@ -13,6 +14,7 @@ public partial class ChallengeCompeteDatum
|
||||
public DateTime CreateTime { get; set; }
|
||||
public DateTime ExpireTime { get; set; }
|
||||
public uint RequireTitle { get; set; } = 0;
|
||||
public bool OnlyPlayOnce { get; set; } = false;
|
||||
public ShareType Share { get; set; } = ShareType.EveryOne;
|
||||
public CompeteTargetType CompeteTarget { get; set; } = CompeteTargetType.EveryOne;
|
||||
public List<ChallengeCompeteSongDatum> Songs { get; set; } = new();
|
||||
|
@ -7,7 +7,10 @@ public partial class ChallengeCompeteSongDatum
|
||||
public uint CompId { get; set; }
|
||||
public uint SongId { get; set; }
|
||||
public Difficulty Difficulty { get; set; }
|
||||
public short SongOpt { get; set; }
|
||||
public uint? Speed { get; set; } = null;
|
||||
public bool? IsVanishOn { get; set; } = null;
|
||||
public bool? IsInverseOn { get; set; } = null;
|
||||
public RandomType? RandomType { get; set; } = null;
|
||||
public List<ChallengeCompeteBestDatum> BestScores { get; set; } = new();
|
||||
public virtual ChallengeCompeteDatum? ChallengeCompeteData { get; set; }
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace GameDatabase.Migrations
|
||||
{
|
||||
[DbContext(typeof(TaikoDbContext))]
|
||||
[Migration("20240910100030_AddChallengeCompete")]
|
||||
partial class AddChallengeCompete
|
||||
[Migration("20240911133119_AddChallengeCompetion")]
|
||||
partial class AddChallengeCompetion
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@ -182,12 +182,18 @@ namespace GameDatabase.Migrations
|
||||
b.Property<uint>("MaxParticipant")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("OnlyPlayOnce")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RequireTitle")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Share")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("State")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("CompId");
|
||||
|
||||
b.ToTable("ChallengeCompeteData");
|
||||
@ -222,7 +228,16 @@ namespace GameDatabase.Migrations
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<short>("SongOpt")
|
||||
b.Property<bool?>("IsInverseOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("IsVanishOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("RandomType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint?>("Speed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("CompId", "SongId");
|
@ -6,7 +6,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
||||
namespace GameDatabase.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddChallengeCompete : Migration
|
||||
public partial class AddChallengeCompetion : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
@ -18,6 +18,7 @@ namespace GameDatabase.Migrations
|
||||
CompId = table.Column<uint>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
CompeteMode = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
State = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
Baid = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
CompeteName = table.Column<string>(type: "TEXT", nullable: false),
|
||||
CompeteDescribe = table.Column<string>(type: "TEXT", nullable: false),
|
||||
@ -25,6 +26,7 @@ namespace GameDatabase.Migrations
|
||||
CreateTime = table.Column<DateTime>(type: "datetime", nullable: false),
|
||||
ExpireTime = table.Column<DateTime>(type: "datetime", nullable: false),
|
||||
RequireTitle = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
OnlyPlayOnce = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
Share = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
CompeteTarget = table.Column<uint>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
@ -65,7 +67,10 @@ namespace GameDatabase.Migrations
|
||||
CompId = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
SongId = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
Difficulty = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
SongOpt = table.Column<short>(type: "INTEGER", nullable: false)
|
||||
Speed = table.Column<uint>(type: "INTEGER", nullable: true),
|
||||
IsVanishOn = table.Column<bool>(type: "INTEGER", nullable: true),
|
||||
IsInverseOn = table.Column<bool>(type: "INTEGER", nullable: true),
|
||||
RandomType = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
@ -179,12 +179,18 @@ namespace TaikoLocalServer.Migrations
|
||||
b.Property<uint>("MaxParticipant")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("OnlyPlayOnce")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RequireTitle")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Share")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("State")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("CompId");
|
||||
|
||||
b.ToTable("ChallengeCompeteData");
|
||||
@ -219,7 +225,16 @@ namespace TaikoLocalServer.Migrations
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<short>("SongOpt")
|
||||
b.Property<bool?>("IsInverseOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool?>("IsVanishOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("RandomType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint?>("Speed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("CompId", "SongId");
|
||||
|
10
SharedProject/Enums/CompeteState.cs
Normal file
10
SharedProject/Enums/CompeteState.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace SharedProject.Enums;
|
||||
|
||||
public enum CompeteState : uint
|
||||
{
|
||||
Disabled = 0,
|
||||
Normal = 1, // In Progress
|
||||
Waiting = 2, // Waiting for Answer
|
||||
Finished = 3, // Finished Once Compete
|
||||
Rejected = 4 // Rejected Challenge
|
||||
}
|
@ -11,10 +11,60 @@ public class ChallengeCompeteManageController(IChallengeCompeteService challenge
|
||||
public ActionResult<List<ChallengeCompeteDatum>> GetAllChallengeCompete()
|
||||
{
|
||||
List<ChallengeCompeteDatum> datum = challengeCompeteService.GetAllChallengeCompete();
|
||||
foreach (var data in datum)
|
||||
{
|
||||
foreach (var participant in data.Participants)
|
||||
{
|
||||
participant.ChallengeCompeteData = null;
|
||||
}
|
||||
foreach (var song in data.Songs)
|
||||
{
|
||||
song.ChallengeCompeteData = null;
|
||||
foreach (var bestScore in song.BestScores)
|
||||
{
|
||||
bestScore.ChallengeCompeteSongData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(datum);
|
||||
}
|
||||
|
||||
[HttpGet("test/{mode}")]
|
||||
[ServiceFilter(typeof(AuthorizeIfRequiredAttribute))]
|
||||
public ActionResult<List<ChallengeCompeteDatum>> testCreateCompete(uint mode)
|
||||
{
|
||||
ChallengeCompeteInfo info = new()
|
||||
{
|
||||
Name = "测试数据",
|
||||
Desc = "测试数据描述",
|
||||
CompeteMode = (CompeteModeType)mode,
|
||||
MaxParticipant = 100,
|
||||
LastFor = 365,
|
||||
RequiredTitle = 0,
|
||||
ShareType = ShareType.EveryOne,
|
||||
CompeteTargetType = CompeteTargetType.EveryOne,
|
||||
challengeCompeteSongs = [
|
||||
new() {
|
||||
SongId = 1,
|
||||
Difficulty = Difficulty.Oni,
|
||||
RandomType = RandomType.Messy
|
||||
},
|
||||
new() {
|
||||
SongId = 2,
|
||||
Difficulty = Difficulty.Oni,
|
||||
},
|
||||
new() {
|
||||
SongId = 3,
|
||||
Difficulty = Difficulty.Oni,
|
||||
},
|
||||
]
|
||||
};
|
||||
challengeCompeteService.CreateCompete(1, info);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPost("{baid}/createCompete")]
|
||||
[ServiceFilter(typeof(AuthorizeIfRequiredAttribute))]
|
||||
public async Task<IActionResult> CreateCompete(uint baid, ChallengeCompeteInfo challengeCompeteInfo)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using GameDatabase.Context;
|
||||
using SharedProject.Utils;
|
||||
using System.Buffers.Binary;
|
||||
|
||||
namespace TaikoLocalServer.Handlers;
|
||||
@ -26,7 +27,14 @@ public class ChallengeCompeteQueryHandler(TaikoDbContext context, IChallengeComp
|
||||
foreach (var song in compete.Songs)
|
||||
{
|
||||
var songOptions = new byte[2];
|
||||
BinaryPrimitives.WriteInt16LittleEndian(songOptions, song.SongOpt);
|
||||
short songOpt = PlaySettingConverter.PlaySettingToShort(new()
|
||||
{
|
||||
Speed = song.Speed != null ? (uint)song.Speed : 0,
|
||||
IsVanishOn = song.IsVanishOn != null ? (bool)song.IsVanishOn : false,
|
||||
IsInverseOn = song.IsInverseOn != null ? (bool)song.IsInverseOn : false,
|
||||
RandomType = song.RandomType != null ? (RandomType)song.RandomType : RandomType.None,
|
||||
});
|
||||
BinaryPrimitives.WriteInt16LittleEndian(songOptions, songOpt);
|
||||
|
||||
uint myHighScore = 0;
|
||||
foreach (var bestScore in song.BestScores)
|
||||
|
@ -16,6 +16,9 @@ public class ChallengeCompeteInfo
|
||||
[JsonPropertyName("maxParticipant")]
|
||||
public uint MaxParticipant { get; set; }
|
||||
|
||||
[JsonPropertyName("onlyPlayOnce")]
|
||||
public bool OnlyPlayOnce { get; set; }
|
||||
|
||||
[JsonPropertyName("lastFor")]
|
||||
public uint LastFor { get; set; }
|
||||
|
||||
|
@ -11,6 +11,15 @@ public class ChallengeCompeteSongInfo
|
||||
[JsonPropertyName("difficulty")]
|
||||
public Difficulty Difficulty { get; set; }
|
||||
|
||||
[JsonPropertyName("playSetting")]
|
||||
public PlaySetting PlaySetting { get; set; } = new();
|
||||
[JsonPropertyName("speed")]
|
||||
public uint? Speed { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("isVanishOn")]
|
||||
public bool? IsVanishOn { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("isInverseOn")]
|
||||
public bool? IsInverseOn { get; set; } = null;
|
||||
|
||||
[JsonPropertyName("randomType")]
|
||||
public RandomType? RandomType { get; set; } = null;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
using GameDatabase.Context;
|
||||
using SharedProject.Models;
|
||||
using SharedProject.Utils;
|
||||
using Throw;
|
||||
|
||||
@ -17,10 +18,17 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
{
|
||||
return context.ChallengeCompeteData
|
||||
.Include(c => c.Participants)
|
||||
.Include(c => c.Songs)
|
||||
.ThenInclude(s => s.BestScores)
|
||||
.Any(data =>
|
||||
data.State == CompeteState.Normal &&
|
||||
data.CreateTime < DateTime.Now &&
|
||||
data.ExpireTime > DateTime.Now &&
|
||||
data.Participants.Any(participant => participant.Baid == baid && participant.IsActive)
|
||||
data.Participants.Any(participant => participant.Baid == baid && participant.IsActive) &&
|
||||
(
|
||||
// Only Play Once need there is no Score for current Compete
|
||||
!data.OnlyPlayOnce || data.Songs.Any(song => !song.BestScores.Any(s => s.Baid == baid))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -28,16 +36,27 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
{
|
||||
return context.ChallengeCompeteData
|
||||
.Include(c => c.Participants)
|
||||
.Include(c => c.Songs)
|
||||
.ThenInclude(s => s.BestScores)
|
||||
.Where(data =>
|
||||
data.State == CompeteState.Normal &&
|
||||
data.CreateTime < DateTime.Now &&
|
||||
data.ExpireTime > DateTime.Now &&
|
||||
data.Participants.Any(participant => participant.Baid == baid)
|
||||
data.Participants.Any(participant => participant.Baid == baid && participant.IsActive) &&
|
||||
(
|
||||
// Only Play Once need there is no Score for current Compete
|
||||
!data.OnlyPlayOnce || data.Songs.Any(song => !song.BestScores.Any(s => s.Baid == baid))
|
||||
)
|
||||
).ToList();
|
||||
}
|
||||
|
||||
public List<ChallengeCompeteDatum> GetAllChallengeCompete()
|
||||
{
|
||||
return context.ChallengeCompeteData.Where(data => true).ToList();
|
||||
return context.ChallengeCompeteData
|
||||
.Include(c => c.Participants)
|
||||
.Include(c => c.Songs)
|
||||
.ThenInclude(s => s.BestScores)
|
||||
.Where(data => true).ToList();
|
||||
}
|
||||
|
||||
public async Task CreateCompete(uint baid, ChallengeCompeteInfo challengeCompeteInfo)
|
||||
@ -46,10 +65,12 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
{
|
||||
CompId = context.ChallengeCompeteData.Any() ? context.ChallengeCompeteData.AsEnumerable().Max(c => c.CompId) + 1 : 1,
|
||||
CompeteMode = challengeCompeteInfo.CompeteMode,
|
||||
State = CompeteState.Normal,
|
||||
Baid = baid,
|
||||
CompeteName = challengeCompeteInfo.Name,
|
||||
CompeteDescribe = challengeCompeteInfo.Desc,
|
||||
MaxParticipant = challengeCompeteInfo.MaxParticipant,
|
||||
OnlyPlayOnce = challengeCompeteInfo.OnlyPlayOnce,
|
||||
CreateTime = DateTime.Now,
|
||||
ExpireTime = DateTime.Now.AddDays(challengeCompeteInfo.LastFor),
|
||||
RequireTitle = challengeCompeteInfo.RequiredTitle,
|
||||
@ -64,7 +85,10 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
CompId = challengeCompeteData.CompId,
|
||||
SongId = song.SongId,
|
||||
Difficulty = song.Difficulty,
|
||||
SongOpt = PlaySettingConverter.PlaySettingToShort(song.PlaySetting)
|
||||
Speed = song.Speed,
|
||||
IsInverseOn = song.IsInverseOn,
|
||||
IsVanishOn = song.IsVanishOn,
|
||||
RandomType = song.RandomType
|
||||
};
|
||||
await context.AddAsync(challengeCompeteSongData);
|
||||
}
|
||||
@ -75,6 +99,7 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
IsActive = true
|
||||
};
|
||||
await context.AddAsync(participantDatum);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> ParticipateCompete(uint compId, uint baid)
|
||||
@ -95,6 +120,7 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
IsActive = true,
|
||||
};
|
||||
await context.AddAsync(participantDatum);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -104,11 +130,13 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
ChallengeCompeteDatum challengeCompeteData = new()
|
||||
{
|
||||
CompId = context.ChallengeCompeteData.Any() ? context.ChallengeCompeteData.AsEnumerable().Max(c => c.CompId) + 1 : 1,
|
||||
CompeteMode = challengeCompeteInfo.CompeteMode,
|
||||
CompeteMode = CompeteModeType.Chanllenge,
|
||||
State = CompeteState.Waiting,
|
||||
Baid = baid,
|
||||
CompeteName = challengeCompeteInfo.Name,
|
||||
CompeteDescribe = challengeCompeteInfo.Desc,
|
||||
MaxParticipant = challengeCompeteInfo.MaxParticipant,
|
||||
MaxParticipant = 2,
|
||||
OnlyPlayOnce = challengeCompeteInfo.OnlyPlayOnce,
|
||||
CreateTime = DateTime.Now,
|
||||
ExpireTime = DateTime.Now.AddDays(challengeCompeteInfo.LastFor),
|
||||
RequireTitle = challengeCompeteInfo.RequiredTitle,
|
||||
@ -123,7 +151,10 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
CompId = challengeCompeteData.CompId,
|
||||
SongId = song.SongId,
|
||||
Difficulty = song.Difficulty,
|
||||
SongOpt = PlaySettingConverter.PlaySettingToShort(song.PlaySetting)
|
||||
Speed = song.Speed,
|
||||
IsInverseOn = song.IsInverseOn,
|
||||
IsVanishOn = song.IsVanishOn,
|
||||
RandomType = song.RandomType
|
||||
};
|
||||
await context.AddAsync(challengeCompeteSongData);
|
||||
}
|
||||
@ -141,6 +172,7 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
IsActive = false
|
||||
};
|
||||
await context.AddAsync(targetDatum);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> AnswerChallenge(uint compId, uint baid, bool accept)
|
||||
@ -158,6 +190,7 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
|
||||
if (accept)
|
||||
{
|
||||
challengeCompete.State = CompeteState.Normal;
|
||||
foreach (var participant in challengeCompete.Participants)
|
||||
{
|
||||
participant.IsActive = true;
|
||||
@ -166,8 +199,10 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Remove(challengeCompete);
|
||||
challengeCompete.State = CompeteState.Rejected;
|
||||
}
|
||||
context.Update(challengeCompete);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -176,15 +211,22 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
{
|
||||
List<ChallengeCompeteDatum> challengeCompetes = context.ChallengeCompeteData
|
||||
.Include(e => e.Songs)
|
||||
.ThenInclude(s => s.BestScores)
|
||||
.Include(e => e.Participants)
|
||||
.Where(e => e.CreateTime < DateTime.Now && DateTime.Now < e.ExpireTime)
|
||||
.Where(e => e.Participants.Any(d => d.Baid == baid && d.IsActive))
|
||||
.Where(e => e.Songs.Any(d => d.SongId == playData.SongId && d.SongOpt == option))
|
||||
.Where(e => e.Songs.Any(d => d.SongId == playData.SongId && d.Difficulty == playData.Difficulty))
|
||||
.Where(e => !e.OnlyPlayOnce || e.Songs.Any(song => !song.BestScores.Any(s => s.Baid == baid)))
|
||||
.ToList();
|
||||
PlaySetting setting = PlaySettingConverter.ShortToPlaySetting(option);
|
||||
foreach (var challengeCompete in challengeCompetes)
|
||||
{
|
||||
ChallengeCompeteSongDatum? song = challengeCompete.Songs.Find(e => e.SongId == playData.SongId);
|
||||
if (song == null || song.Difficulty != playData.Difficulty) continue;
|
||||
ChallengeCompeteSongDatum? song = challengeCompete.Songs.Find(e => e.SongId == playData.SongId && e.Difficulty == playData.Difficulty);
|
||||
if (song == null) continue;
|
||||
if (song.Speed != null && song.Speed != setting.Speed) continue;
|
||||
if (song.IsVanishOn != null && song.IsVanishOn != setting.IsVanishOn) continue;
|
||||
if (song.IsInverseOn != null && song.IsInverseOn != setting.IsInverseOn) continue;
|
||||
if (song.RandomType != null && song.RandomType != setting.RandomType) continue;
|
||||
|
||||
ChallengeCompeteBestDatum? bestScore = song.BestScores.Find(e => e.Baid == baid);
|
||||
if (bestScore == null)
|
||||
@ -208,7 +250,7 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
Skipped = playData.Skipped
|
||||
});
|
||||
}
|
||||
else if (bestScore.Score < playData.Score)
|
||||
else if (!challengeCompete.OnlyPlayOnce && bestScore.Score < playData.Score)
|
||||
{
|
||||
bestScore.Crown = playData.Crown;
|
||||
bestScore.Score = playData.Score;
|
||||
@ -224,5 +266,6 @@ public class ChallengeCompeteService : IChallengeCompeteService
|
||||
context.Update(bestScore);
|
||||
}
|
||||
}
|
||||
await context.AddRangeAsync();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user