Test token table refactor
This commit is contained in:
parent
8901e92e55
commit
be1d6f1581
@ -10,6 +10,7 @@ public partial class TaikoDbContext
|
||||
public virtual DbSet<DanStageScoreDatum> DanStageScoreData { get; set; } = null!;
|
||||
public virtual DbSet<AiScoreDatum> AiScoreData { get; set; } = null!;
|
||||
public virtual DbSet<AiSectionScoreDatum> AiSectionScoreData { get; set; } = null!;
|
||||
public virtual DbSet<Token> Tokens { get; set; } = null!;
|
||||
|
||||
partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
|
||||
{
|
||||
@ -60,5 +61,16 @@ public partial class TaikoDbContext
|
||||
.HasForeignKey(d => new { d.Baid, d.SongId, d.Difficulty })
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Token>(entity =>
|
||||
{
|
||||
entity.HasKey(e => new { e.Baid, e.Id });
|
||||
|
||||
entity.HasOne(d => d.Datum)
|
||||
.WithMany(p => p.Tokens)
|
||||
.HasPrincipalKey(p => p.Baid)
|
||||
.HasForeignKey(d => d.Baid)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
}
|
||||
}
|
12
GameDatabase/Entities/Token.cs
Normal file
12
GameDatabase/Entities/Token.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace GameDatabase.Entities;
|
||||
|
||||
public class Token
|
||||
{
|
||||
public uint Baid { get; set; }
|
||||
|
||||
public int Id { get; set; }
|
||||
|
||||
public int Count { get; set; }
|
||||
|
||||
public virtual UserDatum? Datum { get; set; }
|
||||
}
|
@ -31,7 +31,7 @@ namespace GameDatabase.Entities
|
||||
public bool DisplayAchievement { get; set; }
|
||||
public Difficulty AchievementDisplayDifficulty { get; set; }
|
||||
public int AiWinCount { get; set; }
|
||||
public string TokenCountDict { get; set; } = "{}";
|
||||
public List<Token> Tokens { get; set; } = new();
|
||||
public string UnlockedSongIdList { get; set; } = "[]";
|
||||
public bool IsAdmin { get; set; }
|
||||
}
|
||||
|
519
GameDatabase/Migrations/20240309102758_SeparateTokens.Designer.cs
generated
Normal file
519
GameDatabase/Migrations/20240309102758_SeparateTokens.Designer.cs
generated
Normal file
@ -0,0 +1,519 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using GameDatabase.Context;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace GameDatabase.Migrations
|
||||
{
|
||||
[DbContext(typeof(TaikoDbContext))]
|
||||
[Migration("20240309102758_SeparateTokens")]
|
||||
partial class SeparateTokens
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.0-rc.2.23480.1");
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsWin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "SongId", "Difficulty");
|
||||
|
||||
b.ToTable("AiScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SectionIndex")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Crown")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DrumrollCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("GoodCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsWin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("MissCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("OkCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Score")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
|
||||
|
||||
b.ToTable("AiSectionScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
|
||||
{
|
||||
b.Property<string>("AccessCode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("AccessCode");
|
||||
|
||||
b.HasIndex("Baid");
|
||||
|
||||
b.ToTable("Card", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Salt")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Baid");
|
||||
|
||||
b.ToTable("Credential", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DanId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DanType")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(1);
|
||||
|
||||
b.Property<uint>("ArrivalSongCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ClearState")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(0u);
|
||||
|
||||
b.Property<uint>("ComboCountTotal")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SoulGaugeTotal")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "DanId", "DanType");
|
||||
|
||||
b.ToTable("DanScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DanId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("DanType")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER")
|
||||
.HasDefaultValue(1);
|
||||
|
||||
b.Property<uint>("SongNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("BadCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ComboCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DrumrollCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("GoodCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("HighScore")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("OkCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("PlayScore")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("TotalHitCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "DanId", "DanType", "SongNumber");
|
||||
|
||||
b.ToTable("DanStageScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("BestCrown")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("BestRate")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("BestScore")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("BestScoreRank")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "SongId", "Difficulty");
|
||||
|
||||
b.ToTable("SongBestData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ComboCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Crown")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("Difficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DrumrollCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("GoodCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("HitCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("MissCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("OkCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("PlayTime")
|
||||
.HasColumnType("datetime");
|
||||
|
||||
b.Property<uint>("Score")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ScoreRank")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ScoreRate")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("Skipped")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongNumber")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Baid");
|
||||
|
||||
b.ToTable("SongPlayData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Token", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "Id");
|
||||
|
||||
b.ToTable("Tokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("AchievementDisplayDifficulty")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AiWinCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ColorBody")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ColorFace")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ColorLimb")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CostumeData")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CostumeFlgArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DifficultyPlayedArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DifficultySettingArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("DisplayAchievement")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("DisplayDan")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("FavoriteSongsArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("GenericInfoFlgArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsAdmin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsSkipOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsVoiceOn")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastPlayDatetime")
|
||||
.HasColumnType("datetime");
|
||||
|
||||
b.Property<uint>("LastPlayMode")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("MyDonName")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("MyDonNameLanguage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("NotesPosition")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<short>("OptionSetting")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SelectedToneId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TitleFlgArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<uint>("TitlePlateId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ToneFlgArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UnlockedSongIdList")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Baid");
|
||||
|
||||
b.ToTable("UserData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.AiScoreDatum", "Parent")
|
||||
.WithMany("AiSectionScoreData")
|
||||
.HasForeignKey("Baid", "SongId", "Difficulty")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.DanScoreDatum", "Parent")
|
||||
.WithMany("DanStageScoreData")
|
||||
.HasForeignKey("Baid", "DanId", "DanType")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Parent");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
|
||||
.WithMany()
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Token", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Datum")
|
||||
.WithMany("Tokens")
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Datum");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
|
||||
{
|
||||
b.Navigation("AiSectionScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
|
||||
{
|
||||
b.Navigation("DanStageScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
|
||||
{
|
||||
b.Navigation("Tokens");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
71
GameDatabase/Migrations/20240309102758_SeparateTokens.cs
Normal file
71
GameDatabase/Migrations/20240309102758_SeparateTokens.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using System.Text.Json;
|
||||
using GameDatabase.Context;
|
||||
using GameDatabase.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace GameDatabase.Migrations
|
||||
{
|
||||
internal record Pair(uint Baid, string TokenCountDict);
|
||||
/// <inheritdoc />
|
||||
public partial class SeparateTokens : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
using var context = new TaikoDbContext();
|
||||
var tokenJsons = context.Database
|
||||
.SqlQuery<Pair>($"SELECT Baid, TokenCountDict FROM UserData")
|
||||
.ToList();
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Tokens",
|
||||
columns: table => new
|
||||
{
|
||||
Baid = table.Column<uint>(type: "INTEGER", nullable: false),
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Count = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Tokens", x => new { x.Baid, x.Id });
|
||||
table.ForeignKey(
|
||||
name: "FK_Tokens_UserData_Baid",
|
||||
column: x => x.Baid,
|
||||
principalTable: "UserData",
|
||||
principalColumn: "Baid",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
foreach (var (baid, tokenCountDict) in tokenJsons)
|
||||
{
|
||||
var tokenDict = JsonSerializer.Deserialize<Dictionary<int, int>>(tokenCountDict);
|
||||
foreach (var (key, value) in tokenDict)
|
||||
{
|
||||
migrationBuilder.InsertData(
|
||||
table: "Tokens",
|
||||
columns: new[] { "Baid", "Id", "Count" },
|
||||
values: new object[] { baid, key, value });
|
||||
}
|
||||
}
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TokenCountDict",
|
||||
table: "UserData");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Tokens");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "TokenCountDict",
|
||||
table: "UserData",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
@ -38,7 +38,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
@ -81,7 +81,7 @@ namespace TaikoLocalServer.Migrations
|
||||
b.Property<string>("AccessCode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("AccessCode");
|
||||
@ -93,7 +93,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Password")
|
||||
@ -111,7 +111,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DanId")
|
||||
@ -143,7 +143,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("DanId")
|
||||
@ -188,7 +188,7 @@ namespace TaikoLocalServer.Migrations
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("SongId")
|
||||
@ -220,7 +220,7 @@ namespace TaikoLocalServer.Migrations
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("ComboCount")
|
||||
@ -275,9 +275,25 @@ namespace TaikoLocalServer.Migrations
|
||||
b.ToTable("SongPlayData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Token", b =>
|
||||
{
|
||||
b.Property<uint>("Baid")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Id")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Count")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Baid", "Id");
|
||||
|
||||
b.ToTable("Tokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
|
||||
{
|
||||
b.Property<ulong>("Baid")
|
||||
b.Property<uint>("Baid")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
@ -368,10 +384,6 @@ namespace TaikoLocalServer.Migrations
|
||||
b.Property<uint>("TitlePlateId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("TokenCountDict")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ToneFlgArray")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
@ -473,6 +485,17 @@ namespace TaikoLocalServer.Migrations
|
||||
b.Navigation("Ba");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.Token", b =>
|
||||
{
|
||||
b.HasOne("GameDatabase.Entities.UserDatum", "Datum")
|
||||
.WithMany("Tokens")
|
||||
.HasForeignKey("Baid")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Datum");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
|
||||
{
|
||||
b.Navigation("AiSectionScoreData");
|
||||
@ -482,6 +505,11 @@ namespace TaikoLocalServer.Migrations
|
||||
{
|
||||
b.Navigation("DanStageScoreData");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
|
||||
{
|
||||
b.Navigation("Tokens");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
using GameDatabase.Entities;
|
||||
using Throw;
|
||||
|
||||
namespace TaikoLocalServer.Controllers.Game;
|
||||
@ -23,32 +24,25 @@ public class AddTokenCountController : BaseController<AddTokenCountController>
|
||||
var user = await userDatumService.GetFirstUserDatumOrNull(request.Baid);
|
||||
user.ThrowIfNull($"User with baid {request.Baid} does not exist!");
|
||||
|
||||
var tokenCountDict = new Dictionary<uint, int>();
|
||||
try
|
||||
{
|
||||
tokenCountDict = !string.IsNullOrEmpty(user.TokenCountDict)
|
||||
? JsonSerializer.Deserialize<Dictionary<uint, int>>(user.TokenCountDict)
|
||||
: new Dictionary<uint, int>();
|
||||
}
|
||||
catch (JsonException e)
|
||||
{
|
||||
Logger.LogError(e, "Parsing TokenCountDict data for user with baid {Request} failed!", request.Baid);
|
||||
}
|
||||
|
||||
tokenCountDict.ThrowIfNull("TokenCountDict should never be null");
|
||||
|
||||
foreach (var addTokenCountData in request.AryAddTokenCountDatas)
|
||||
{
|
||||
var tokenId = addTokenCountData.TokenId;
|
||||
var addTokenCount = addTokenCountData.AddTokenCount;
|
||||
|
||||
if (tokenCountDict.ContainsKey(tokenId))
|
||||
tokenCountDict[tokenId] += addTokenCount;
|
||||
var token = user.Tokens.FirstOrDefault(t => t.Id == tokenId);
|
||||
if (token != null)
|
||||
{
|
||||
token.Count += addTokenCount;
|
||||
}
|
||||
else
|
||||
tokenCountDict.Add(tokenId, addTokenCount);
|
||||
{
|
||||
user.Tokens.Add(new Token
|
||||
{
|
||||
Id = (int)tokenId,
|
||||
Count = addTokenCount
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
user.TokenCountDict = JsonSerializer.Serialize(tokenCountDict);
|
||||
await userDatumService.UpdateUserDatum(user);
|
||||
|
||||
var response = new AddTokenCountResponse
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
using GameDatabase.Entities;
|
||||
using Throw;
|
||||
|
||||
namespace TaikoLocalServer.Controllers.Game;
|
||||
@ -60,20 +61,6 @@ public class GetTokenCountController : BaseController<GetTokenCountController>
|
||||
machina4TokenId
|
||||
};
|
||||
|
||||
var tokenCountDict = new Dictionary<uint, int>();
|
||||
try
|
||||
{
|
||||
tokenCountDict = !string.IsNullOrEmpty(user.TokenCountDict)
|
||||
? JsonSerializer.Deserialize<Dictionary<uint, int>>(user.TokenCountDict)
|
||||
: new Dictionary<uint, int>();
|
||||
}
|
||||
catch (JsonException e)
|
||||
{
|
||||
Logger.LogError(e, "Parsing TokenCountDict data for user with baid {Request} failed!", request.Baid);
|
||||
}
|
||||
|
||||
tokenCountDict.ThrowIfNull("TokenCountDict should never be null");
|
||||
|
||||
var response = new GetTokenCountResponse
|
||||
{
|
||||
Result = 1
|
||||
@ -83,15 +70,22 @@ public class GetTokenCountController : BaseController<GetTokenCountController>
|
||||
{
|
||||
if (tokenDataId <= 0) continue;
|
||||
var castedTokenDataId = (uint)tokenDataId;
|
||||
tokenCountDict.TryAdd(castedTokenDataId, 0);
|
||||
if (user.Tokens.All(token => token.Id != castedTokenDataId))
|
||||
{
|
||||
user.Tokens.Add(new Token
|
||||
{
|
||||
Id = (int)castedTokenDataId,
|
||||
Count = 0
|
||||
});
|
||||
}
|
||||
var tokenCount = user.Tokens.First(token => token.Id == castedTokenDataId).Count;
|
||||
response.AryTokenCountDatas.Add(new GetTokenCountResponse.TokenCountData
|
||||
{
|
||||
TokenCount = tokenCountDict[castedTokenDataId],
|
||||
TokenCount = tokenCount,
|
||||
TokenId = castedTokenDataId
|
||||
});
|
||||
}
|
||||
|
||||
user.TokenCountDict = JsonSerializer.Serialize(tokenCountDict);
|
||||
await userDatumService.UpdateUserDatum(user);
|
||||
|
||||
return Ok(response);
|
||||
|
@ -43,7 +43,6 @@ public class MyDonEntryController : BaseController<MyDonEntryController>
|
||||
TitleFlgArray = "[]",
|
||||
CostumeFlgArray = "[[0],[0],[0],[0],[0]]",
|
||||
GenericInfoFlgArray = "[]",
|
||||
TokenCountDict = "{}",
|
||||
UnlockedSongIdList = "[]"
|
||||
};
|
||||
await userDatumService.InsertUserDatum(newUser);
|
||||
|
@ -23,7 +23,7 @@ public class SongPurchaseController : BaseController<SongPurchaseController>
|
||||
var user = await userDatumService.GetFirstUserDatumOrNull(request.Baid);
|
||||
user.ThrowIfNull($"User with baid {request.Baid} does not exist!");
|
||||
|
||||
var tokenCountDict = new Dictionary<uint, int>();
|
||||
/*var tokenCountDict = new Dictionary<uint, int>();
|
||||
try
|
||||
{
|
||||
tokenCountDict = !string.IsNullOrEmpty(user.TokenCountDict)
|
||||
@ -35,7 +35,7 @@ public class SongPurchaseController : BaseController<SongPurchaseController>
|
||||
Logger.LogError(e, "Parsing TokenCountDict data for user with baid {Request} failed!", request.Baid);
|
||||
}
|
||||
|
||||
tokenCountDict.ThrowIfNull("TokenCountDict should never be null");
|
||||
tokenCountDict.ThrowIfNull("TokenCountDict should never be null");*/
|
||||
|
||||
Logger.LogInformation("Original UnlockedSongIdList: {UnlockedSongIdList}", user.UnlockedSongIdList);
|
||||
|
||||
@ -53,11 +53,21 @@ public class SongPurchaseController : BaseController<SongPurchaseController>
|
||||
|
||||
unlockedSongIdList.ThrowIfNull("UnlockedSongIdList should never be null");
|
||||
|
||||
if (tokenCountDict.ContainsKey(request.TokenId)) tokenCountDict[request.TokenId] -= (int)request.Price;
|
||||
//if (tokenCountDict.ContainsKey(request.TokenId)) tokenCountDict[request.TokenId] -= (int)request.Price;
|
||||
|
||||
var token = user.Tokens.FirstOrDefault(t => t.Id == request.TokenId);
|
||||
if (token is not null && token.Count >= request.Price)
|
||||
{
|
||||
token.Count -= (int)request.Price;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("User with baid {Baid} does not have enough tokens to purchase song with id {SongNo}!", request.Baid, request.SongNo);
|
||||
return Ok(new SongPurchaseResponse { Result = 0 });
|
||||
}
|
||||
|
||||
if (!unlockedSongIdList.Contains(request.SongNo)) unlockedSongIdList.Add(request.SongNo);
|
||||
|
||||
user.TokenCountDict = JsonSerializer.Serialize(tokenCountDict);
|
||||
user.UnlockedSongIdList = JsonSerializer.Serialize(unlockedSongIdList);
|
||||
|
||||
Logger.LogInformation("Updated UnlockedSongIdList: {UnlockedSongIdList}", user.UnlockedSongIdList);
|
||||
@ -67,7 +77,7 @@ public class SongPurchaseController : BaseController<SongPurchaseController>
|
||||
var response = new SongPurchaseResponse
|
||||
{
|
||||
Result = 1,
|
||||
TokenCount = tokenCountDict[request.TokenId]
|
||||
TokenCount = token.Count
|
||||
};
|
||||
|
||||
return Ok(response);
|
||||
|
@ -19,12 +19,16 @@ public class UserDatumService : IUserDatumService
|
||||
|
||||
public async Task<UserDatum?> GetFirstUserDatumOrNull(uint baid)
|
||||
{
|
||||
return await context.UserData.FindAsync(baid);
|
||||
return await context.UserData
|
||||
.Include(d => d.Tokens)
|
||||
.FirstOrDefaultAsync(d => d.Baid == baid);
|
||||
}
|
||||
|
||||
public async Task<UserDatum> GetFirstUserDatumOrDefault(uint baid)
|
||||
{
|
||||
return await context.UserData.FindAsync(baid) ?? new UserDatum();
|
||||
return await context.UserData
|
||||
.Include(d => d.Tokens)
|
||||
.FirstOrDefaultAsync(d => d.Baid == baid) ?? new UserDatum();
|
||||
}
|
||||
|
||||
public async Task<List<UserDatum>> GetAllUserData()
|
||||
|
Loading…
Reference in New Issue
Block a user