init efcore
This commit is contained in:
100
.gitignore
vendored
Normal file
100
.gitignore
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio / Rider / VS Code
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
*.userprefs
|
||||||
|
*.rsuser
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.tlog
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# NuGet
|
||||||
|
*.nupkg
|
||||||
|
*.snupkg
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# MSBuild / test results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
[Bb]uild[Tt]ools/
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# EF Core
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Python (WeaponGrabber)
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
*.egg-info/
|
||||||
|
.pytest_cache/
|
||||||
19
BlueLaminate/BlueLaminate.EFCore/BlueLaminate.EFCore.csproj
Normal file
19
BlueLaminate/BlueLaminate.EFCore/BlueLaminate.EFCore.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="EFCore.NamingConventions" Version="10.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class InventoryItemConfiguration : IEntityTypeConfiguration<InventoryItem>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<InventoryItem> entity)
|
||||||
|
{
|
||||||
|
entity.HasIndex(e => e.AssetId);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany(u => u.InventoryItems)
|
||||||
|
.HasForeignKey(e => e.UserId);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.SkinInstance)
|
||||||
|
.WithMany(i => i.InventoryItems)
|
||||||
|
.HasForeignKey(e => e.SkinInstanceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class PriceHistoryConfiguration : IEntityTypeConfiguration<PriceHistory>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<PriceHistory> entity)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.Price).HasPrecision(18, 2);
|
||||||
|
|
||||||
|
entity.HasIndex(e => new { e.SkinId, e.ConditionId, e.RecordedAt });
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Skin)
|
||||||
|
.WithMany(s => s.PriceHistories)
|
||||||
|
.HasForeignKey(e => e.SkinId);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Condition)
|
||||||
|
.WithMany(c => c.PriceHistories)
|
||||||
|
.HasForeignKey(e => e.ConditionId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class SkinConditionConfiguration : IEntityTypeConfiguration<SkinCondition>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SkinCondition> entity)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.MinFloat).HasColumnType("numeric(10,9)");
|
||||||
|
entity.Property(e => e.MaxFloat).HasColumnType("numeric(10,9)");
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Skin)
|
||||||
|
.WithMany(s => s.Conditions)
|
||||||
|
.HasForeignKey(e => e.SkinId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class SkinConfiguration : IEntityTypeConfiguration<Skin>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Skin> entity)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.FloatMin)
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(0.0m);
|
||||||
|
entity.Property(e => e.FloatMax)
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(1.0m);
|
||||||
|
|
||||||
|
entity.Property(e => e.TrueFloat)
|
||||||
|
.HasComputedColumnSql("float_min = 0.0 AND float_max = 1.0", stored: true);
|
||||||
|
|
||||||
|
entity.HasIndex(e => e.TrueFloat);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Weapon)
|
||||||
|
.WithMany(w => w.Skins)
|
||||||
|
.HasForeignKey(e => e.WeaponId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class SkinInstanceConfiguration : IEntityTypeConfiguration<SkinInstance>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SkinInstance> entity)
|
||||||
|
{
|
||||||
|
entity.Property(e => e.FloatValue).HasColumnType("numeric(10,9)");
|
||||||
|
|
||||||
|
// Primary lookup key for trade fingerprinting.
|
||||||
|
entity.HasIndex(e => e.FloatValue);
|
||||||
|
entity.HasIndex(e => e.PaintSeed);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Skin)
|
||||||
|
.WithMany(s => s.Instances)
|
||||||
|
.HasForeignKey(e => e.SkinId);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.Condition)
|
||||||
|
.WithMany(c => c.Instances)
|
||||||
|
.HasForeignKey(e => e.ConditionId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class SteamUserConfiguration : IEntityTypeConfiguration<SteamUser>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SteamUser> entity)
|
||||||
|
{
|
||||||
|
entity.HasIndex(e => e.SteamId).IsUnique();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class TradeConfiguration : IEntityTypeConfiguration<Trade>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Trade> entity)
|
||||||
|
{
|
||||||
|
entity.HasOne(e => e.FromUser)
|
||||||
|
.WithMany(u => u.TradesSent)
|
||||||
|
.HasForeignKey(e => e.FromUserId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.ToUser)
|
||||||
|
.WithMany(u => u.TradesReceived)
|
||||||
|
.HasForeignKey(e => e.ToUserId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Configurations;
|
||||||
|
|
||||||
|
public class TradeItemConfiguration : IEntityTypeConfiguration<TradeItem>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<TradeItem> entity)
|
||||||
|
{
|
||||||
|
entity.HasOne(e => e.Trade)
|
||||||
|
.WithMany(t => t.TradeItems)
|
||||||
|
.HasForeignKey(e => e.TradeId);
|
||||||
|
|
||||||
|
entity.HasOne(e => e.InventoryItem)
|
||||||
|
.WithMany(i => i.TradeItems)
|
||||||
|
.HasForeignKey(e => e.InventoryItemId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using BlueLaminate.EFCore.Configurations;
|
||||||
|
using BlueLaminate.EFCore.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Data;
|
||||||
|
|
||||||
|
public class SkinTrackerDbContext : DbContext
|
||||||
|
{
|
||||||
|
static SkinTrackerDbContext()
|
||||||
|
{
|
||||||
|
// Store and read all timestamps as UTC (timestamptz). Required so that
|
||||||
|
// DateTimeOffset properties round-trip correctly with Npgsql.
|
||||||
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SkinTrackerDbContext(DbContextOptions<SkinTrackerDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<Weapon> Weapons => Set<Weapon>();
|
||||||
|
public DbSet<Skin> Skins => Set<Skin>();
|
||||||
|
public DbSet<SkinCondition> SkinConditions => Set<SkinCondition>();
|
||||||
|
public DbSet<SteamUser> SteamUsers => Set<SteamUser>();
|
||||||
|
public DbSet<SkinInstance> SkinInstances => Set<SkinInstance>();
|
||||||
|
public DbSet<InventoryItem> InventoryItems => Set<InventoryItem>();
|
||||||
|
public DbSet<Trade> Trades => Set<Trade>();
|
||||||
|
public DbSet<TradeItem> TradeItems => Set<TradeItem>();
|
||||||
|
public DbSet<PriceHistory> PriceHistories => Set<PriceHistory>();
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
modelBuilder.ApplyConfiguration(new SkinConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new SkinConditionConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new SteamUserConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new SkinInstanceConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new InventoryItemConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new TradeConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new TradeItemConfiguration());
|
||||||
|
modelBuilder.ApplyConfiguration(new PriceHistoryConfiguration());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Data;
|
||||||
|
|
||||||
|
public class SkinTrackerDbContextFactory : IDesignTimeDbContextFactory<SkinTrackerDbContext>
|
||||||
|
{
|
||||||
|
public SkinTrackerDbContext CreateDbContext(string[] args)
|
||||||
|
{
|
||||||
|
var connectionString =
|
||||||
|
Environment.GetEnvironmentVariable("SKINTRACKER_CONNECTION")
|
||||||
|
?? "Host=localhost;Port=5432;Database=skintracker;Username=postgres;Password=postgres";
|
||||||
|
|
||||||
|
var options = new DbContextOptionsBuilder<SkinTrackerDbContext>()
|
||||||
|
.UseNpgsql(connectionString)
|
||||||
|
.UseSnakeCaseNamingConvention()
|
||||||
|
.Options;
|
||||||
|
|
||||||
|
return new SkinTrackerDbContext(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using BlueLaminate.EFCore.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.DependencyInjection;
|
||||||
|
|
||||||
|
public static class ServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddSkinTrackerData(
|
||||||
|
this IServiceCollection services,
|
||||||
|
string connectionString)
|
||||||
|
{
|
||||||
|
services.AddDbContext<SkinTrackerDbContext>(options =>
|
||||||
|
options
|
||||||
|
.UseNpgsql(connectionString)
|
||||||
|
.UseSnakeCaseNamingConvention());
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
BlueLaminate/BlueLaminate.EFCore/Entities/InventoryItem.cs
Normal file
16
BlueLaminate/BlueLaminate.EFCore/Entities/InventoryItem.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class InventoryItem
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int UserId { get; set; }
|
||||||
|
public SteamUser User { get; set; } = null!;
|
||||||
|
public int SkinInstanceId { get; set; }
|
||||||
|
public SkinInstance SkinInstance { get; set; } = null!;
|
||||||
|
|
||||||
|
// Steam asset ID — changes on trade, not a stable identifier.
|
||||||
|
public string AssetId { get; set; } = null!;
|
||||||
|
public DateTimeOffset AcquiredAt { get; set; }
|
||||||
|
|
||||||
|
public ICollection<TradeItem> TradeItems { get; set; } = new List<TradeItem>();
|
||||||
|
}
|
||||||
15
BlueLaminate/BlueLaminate.EFCore/Entities/PriceHistory.cs
Normal file
15
BlueLaminate/BlueLaminate.EFCore/Entities/PriceHistory.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class PriceHistory
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SkinId { get; set; }
|
||||||
|
public Skin Skin { get; set; } = null!;
|
||||||
|
public int ConditionId { get; set; }
|
||||||
|
public SkinCondition Condition { get; set; } = null!;
|
||||||
|
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
public string Currency { get; set; } = null!;
|
||||||
|
public DateTimeOffset RecordedAt { get; set; }
|
||||||
|
public string Source { get; set; } = null!;
|
||||||
|
}
|
||||||
24
BlueLaminate/BlueLaminate.EFCore/Entities/Skin.cs
Normal file
24
BlueLaminate/BlueLaminate.EFCore/Entities/Skin.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class Skin
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int WeaponId { get; set; }
|
||||||
|
public Weapon Weapon { get; set; } = null!;
|
||||||
|
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
public string Rarity { get; set; } = null!;
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public decimal FloatMin { get; set; }
|
||||||
|
public decimal FloatMax { get; set; }
|
||||||
|
|
||||||
|
// Computed in the database: float_min = 0.0 AND float_max = 1.0.
|
||||||
|
// A skin with a capped float range behaves differently in tradeup calculations.
|
||||||
|
public bool TrueFloat { get; private set; }
|
||||||
|
|
||||||
|
public ICollection<SkinCondition> Conditions { get; set; } = new List<SkinCondition>();
|
||||||
|
public ICollection<SkinInstance> Instances { get; set; } = new List<SkinInstance>();
|
||||||
|
public ICollection<PriceHistory> PriceHistories { get; set; } = new List<PriceHistory>();
|
||||||
|
}
|
||||||
15
BlueLaminate/BlueLaminate.EFCore/Entities/SkinCondition.cs
Normal file
15
BlueLaminate/BlueLaminate.EFCore/Entities/SkinCondition.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class SkinCondition
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SkinId { get; set; }
|
||||||
|
public Skin Skin { get; set; } = null!;
|
||||||
|
|
||||||
|
public string Condition { get; set; } = null!;
|
||||||
|
public decimal MinFloat { get; set; }
|
||||||
|
public decimal MaxFloat { get; set; }
|
||||||
|
|
||||||
|
public ICollection<SkinInstance> Instances { get; set; } = new List<SkinInstance>();
|
||||||
|
public ICollection<PriceHistory> PriceHistories { get; set; } = new List<PriceHistory>();
|
||||||
|
}
|
||||||
20
BlueLaminate/BlueLaminate.EFCore/Entities/SkinInstance.cs
Normal file
20
BlueLaminate/BlueLaminate.EFCore/Entities/SkinInstance.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class SkinInstance
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int SkinId { get; set; }
|
||||||
|
public Skin Skin { get; set; } = null!;
|
||||||
|
public int ConditionId { get; set; }
|
||||||
|
public SkinCondition Condition { get; set; } = null!;
|
||||||
|
|
||||||
|
// FloatValue + PaintSeed form a stable fingerprint across trades; the Steam
|
||||||
|
// asset_id changes on every trade but these do not.
|
||||||
|
public decimal FloatValue { get; set; }
|
||||||
|
public string PaintSeed { get; set; } = null!;
|
||||||
|
public bool StatTrak { get; set; }
|
||||||
|
public bool Souvenir { get; set; }
|
||||||
|
public DateTimeOffset FirstSeenAt { get; set; }
|
||||||
|
|
||||||
|
public ICollection<InventoryItem> InventoryItems { get; set; } = new List<InventoryItem>();
|
||||||
|
}
|
||||||
13
BlueLaminate/BlueLaminate.EFCore/Entities/SteamUser.cs
Normal file
13
BlueLaminate/BlueLaminate.EFCore/Entities/SteamUser.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class SteamUser
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string SteamId { get; set; } = null!;
|
||||||
|
public string? DisplayName { get; set; }
|
||||||
|
public DateTimeOffset LastSyncedAt { get; set; }
|
||||||
|
|
||||||
|
public ICollection<InventoryItem> InventoryItems { get; set; } = new List<InventoryItem>();
|
||||||
|
public ICollection<Trade> TradesSent { get; set; } = new List<Trade>();
|
||||||
|
public ICollection<Trade> TradesReceived { get; set; } = new List<Trade>();
|
||||||
|
}
|
||||||
15
BlueLaminate/BlueLaminate.EFCore/Entities/Trade.cs
Normal file
15
BlueLaminate/BlueLaminate.EFCore/Entities/Trade.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class Trade
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int FromUserId { get; set; }
|
||||||
|
public SteamUser FromUser { get; set; } = null!;
|
||||||
|
public int ToUserId { get; set; }
|
||||||
|
public SteamUser ToUser { get; set; } = null!;
|
||||||
|
|
||||||
|
public DateTimeOffset TradedAt { get; set; }
|
||||||
|
public string? SteamTradeId { get; set; }
|
||||||
|
|
||||||
|
public ICollection<TradeItem> TradeItems { get; set; } = new List<TradeItem>();
|
||||||
|
}
|
||||||
10
BlueLaminate/BlueLaminate.EFCore/Entities/TradeItem.cs
Normal file
10
BlueLaminate/BlueLaminate.EFCore/Entities/TradeItem.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class TradeItem
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int TradeId { get; set; }
|
||||||
|
public Trade Trade { get; set; } = null!;
|
||||||
|
public int InventoryItemId { get; set; }
|
||||||
|
public InventoryItem InventoryItem { get; set; } = null!;
|
||||||
|
}
|
||||||
11
BlueLaminate/BlueLaminate.EFCore/Entities/Weapon.cs
Normal file
11
BlueLaminate/BlueLaminate.EFCore/Entities/Weapon.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace BlueLaminate.EFCore.Entities;
|
||||||
|
|
||||||
|
public class Weapon
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = null!;
|
||||||
|
public string Type { get; set; } = null!;
|
||||||
|
public string Team { get; set; } = null!;
|
||||||
|
|
||||||
|
public ICollection<Skin> Skins { get; set; } = new List<Skin>();
|
||||||
|
}
|
||||||
573
BlueLaminate/BlueLaminate.EFCore/Migrations/20260529170710_InitialCreate.Designer.cs
generated
Normal file
573
BlueLaminate/BlueLaminate.EFCore/Migrations/20260529170710_InitialCreate.Designer.cs
generated
Normal file
@@ -0,0 +1,573 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BlueLaminate.EFCore.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SkinTrackerDbContext))]
|
||||||
|
[Migration("20260529170710_InitialCreate")]
|
||||||
|
partial class InitialCreate
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("AcquiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("acquired_at");
|
||||||
|
|
||||||
|
b.Property<string>("AssetId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("asset_id");
|
||||||
|
|
||||||
|
b.Property<int>("SkinInstanceId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_instance_id");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("user_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_inventory_items");
|
||||||
|
|
||||||
|
b.HasIndex("AssetId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_asset_id");
|
||||||
|
|
||||||
|
b.HasIndex("SkinInstanceId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_skin_instance_id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_user_id");
|
||||||
|
|
||||||
|
b.ToTable("inventory_items", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.PriceHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ConditionId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("condition_id");
|
||||||
|
|
||||||
|
b.Property<string>("Currency")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("currency");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)")
|
||||||
|
.HasColumnName("price");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("RecordedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("recorded_at");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.Property<string>("Source")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("source");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_price_histories");
|
||||||
|
|
||||||
|
b.HasIndex("ConditionId")
|
||||||
|
.HasDatabaseName("ix_price_histories_condition_id");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId", "ConditionId", "RecordedAt")
|
||||||
|
.HasDatabaseName("ix_price_histories_skin_id_condition_id_recorded_at");
|
||||||
|
|
||||||
|
b.ToTable("price_histories", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("description");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatMax")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(1.0m)
|
||||||
|
.HasColumnName("float_max");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatMin")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(0.0m)
|
||||||
|
.HasColumnName("float_min");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("image_url");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Rarity")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("rarity");
|
||||||
|
|
||||||
|
b.Property<bool>("TrueFloat")
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("true_float")
|
||||||
|
.HasComputedColumnSql("float_min = 0.0 AND float_max = 1.0", true);
|
||||||
|
|
||||||
|
b.Property<int>("WeaponId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("weapon_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skins");
|
||||||
|
|
||||||
|
b.HasIndex("TrueFloat")
|
||||||
|
.HasDatabaseName("ix_skins_true_float");
|
||||||
|
|
||||||
|
b.HasIndex("WeaponId")
|
||||||
|
.HasDatabaseName("ix_skins_weapon_id");
|
||||||
|
|
||||||
|
b.ToTable("skins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Condition")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("condition");
|
||||||
|
|
||||||
|
b.Property<decimal>("MaxFloat")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("max_float");
|
||||||
|
|
||||||
|
b.Property<decimal>("MinFloat")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("min_float");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skin_conditions");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId")
|
||||||
|
.HasDatabaseName("ix_skin_conditions_skin_id");
|
||||||
|
|
||||||
|
b.ToTable("skin_conditions", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ConditionId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("condition_id");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("FirstSeenAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("first_seen_at");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatValue")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("float_value");
|
||||||
|
|
||||||
|
b.Property<string>("PaintSeed")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("paint_seed");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.Property<bool>("Souvenir")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("souvenir");
|
||||||
|
|
||||||
|
b.Property<bool>("StatTrak")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("stat_trak");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skin_instances");
|
||||||
|
|
||||||
|
b.HasIndex("ConditionId")
|
||||||
|
.HasDatabaseName("ix_skin_instances_condition_id");
|
||||||
|
|
||||||
|
b.HasIndex("FloatValue")
|
||||||
|
.HasDatabaseName("ix_skin_instances_float_value");
|
||||||
|
|
||||||
|
b.HasIndex("PaintSeed")
|
||||||
|
.HasDatabaseName("ix_skin_instances_paint_seed");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId")
|
||||||
|
.HasDatabaseName("ix_skin_instances_skin_id");
|
||||||
|
|
||||||
|
b.ToTable("skin_instances", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SteamUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("display_name");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("LastSyncedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_synced_at");
|
||||||
|
|
||||||
|
b.Property<string>("SteamId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("steam_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_steam_users");
|
||||||
|
|
||||||
|
b.HasIndex("SteamId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_steam_users_steam_id");
|
||||||
|
|
||||||
|
b.ToTable("steam_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("FromUserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("from_user_id");
|
||||||
|
|
||||||
|
b.Property<string>("SteamTradeId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("steam_trade_id");
|
||||||
|
|
||||||
|
b.Property<int>("ToUserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("to_user_id");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("TradedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("traded_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_trades");
|
||||||
|
|
||||||
|
b.HasIndex("FromUserId")
|
||||||
|
.HasDatabaseName("ix_trades_from_user_id");
|
||||||
|
|
||||||
|
b.HasIndex("ToUserId")
|
||||||
|
.HasDatabaseName("ix_trades_to_user_id");
|
||||||
|
|
||||||
|
b.ToTable("trades", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.TradeItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("InventoryItemId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("inventory_item_id");
|
||||||
|
|
||||||
|
b.Property<int>("TradeId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("trade_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_trade_items");
|
||||||
|
|
||||||
|
b.HasIndex("InventoryItemId")
|
||||||
|
.HasDatabaseName("ix_trade_items_inventory_item_id");
|
||||||
|
|
||||||
|
b.HasIndex("TradeId")
|
||||||
|
.HasDatabaseName("ix_trade_items_trade_id");
|
||||||
|
|
||||||
|
b.ToTable("trade_items", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Weapon", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Team")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("team");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("type");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_weapons");
|
||||||
|
|
||||||
|
b.ToTable("weapons", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinInstance", "SkinInstance")
|
||||||
|
.WithMany("InventoryItems")
|
||||||
|
.HasForeignKey("SkinInstanceId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_inventory_items_skin_instances_skin_instance_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "User")
|
||||||
|
.WithMany("InventoryItems")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_inventory_items_steam_users_user_id");
|
||||||
|
|
||||||
|
b.Navigation("SkinInstance");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.PriceHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
|
||||||
|
.WithMany("PriceHistories")
|
||||||
|
.HasForeignKey("ConditionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_price_histories_skin_conditions_condition_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("PriceHistories")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_price_histories_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Condition");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Weapon", "Weapon")
|
||||||
|
.WithMany("Skins")
|
||||||
|
.HasForeignKey("WeaponId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skins_weapons_weapon_id");
|
||||||
|
|
||||||
|
b.Navigation("Weapon");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("Conditions")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_conditions_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("ConditionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_instances_skin_conditions_condition_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_instances_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Condition");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "FromUser")
|
||||||
|
.WithMany("TradesSent")
|
||||||
|
.HasForeignKey("FromUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trades_steam_users_from_user_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "ToUser")
|
||||||
|
.WithMany("TradesReceived")
|
||||||
|
.HasForeignKey("ToUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trades_steam_users_to_user_id");
|
||||||
|
|
||||||
|
b.Navigation("FromUser");
|
||||||
|
|
||||||
|
b.Navigation("ToUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.TradeItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.InventoryItem", "InventoryItem")
|
||||||
|
.WithMany("TradeItems")
|
||||||
|
.HasForeignKey("InventoryItemId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trade_items_inventory_items_inventory_item_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Trade", "Trade")
|
||||||
|
.WithMany("TradeItems")
|
||||||
|
.HasForeignKey("TradeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trade_items_trades_trade_id");
|
||||||
|
|
||||||
|
b.Navigation("InventoryItem");
|
||||||
|
|
||||||
|
b.Navigation("Trade");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("TradeItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Conditions");
|
||||||
|
|
||||||
|
b.Navigation("Instances");
|
||||||
|
|
||||||
|
b.Navigation("PriceHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Instances");
|
||||||
|
|
||||||
|
b.Navigation("PriceHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("InventoryItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SteamUser", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("InventoryItems");
|
||||||
|
|
||||||
|
b.Navigation("TradesReceived");
|
||||||
|
|
||||||
|
b.Navigation("TradesSent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("TradeItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Weapon", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Skins");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,354 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class InitialCreate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "steam_users",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
steam_id = table.Column<string>(type: "text", nullable: false),
|
||||||
|
display_name = table.Column<string>(type: "text", nullable: true),
|
||||||
|
last_synced_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_steam_users", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "weapons",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
type = table.Column<string>(type: "text", nullable: false),
|
||||||
|
team = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_weapons", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "trades",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
from_user_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
to_user_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
traded_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
|
steam_trade_id = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_trades", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_trades_steam_users_from_user_id",
|
||||||
|
column: x => x.from_user_id,
|
||||||
|
principalTable: "steam_users",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_trades_steam_users_to_user_id",
|
||||||
|
column: x => x.to_user_id,
|
||||||
|
principalTable: "steam_users",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "skins",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
weapon_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
rarity = table.Column<string>(type: "text", nullable: false),
|
||||||
|
description = table.Column<string>(type: "text", nullable: true),
|
||||||
|
image_url = table.Column<string>(type: "text", nullable: true),
|
||||||
|
float_min = table.Column<decimal>(type: "numeric(10,9)", nullable: false, defaultValue: 0.0m),
|
||||||
|
float_max = table.Column<decimal>(type: "numeric(10,9)", nullable: false, defaultValue: 1.0m),
|
||||||
|
true_float = table.Column<bool>(type: "boolean", nullable: false, computedColumnSql: "float_min = 0.0 AND float_max = 1.0", stored: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_skins", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_skins_weapons_weapon_id",
|
||||||
|
column: x => x.weapon_id,
|
||||||
|
principalTable: "weapons",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "skin_conditions",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
skin_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
condition = table.Column<string>(type: "text", nullable: false),
|
||||||
|
min_float = table.Column<decimal>(type: "numeric(10,9)", nullable: false),
|
||||||
|
max_float = table.Column<decimal>(type: "numeric(10,9)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_skin_conditions", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_skin_conditions_skins_skin_id",
|
||||||
|
column: x => x.skin_id,
|
||||||
|
principalTable: "skins",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "price_histories",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
skin_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
condition_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
currency = table.Column<string>(type: "text", nullable: false),
|
||||||
|
recorded_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
||||||
|
source = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_price_histories", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_price_histories_skin_conditions_condition_id",
|
||||||
|
column: x => x.condition_id,
|
||||||
|
principalTable: "skin_conditions",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_price_histories_skins_skin_id",
|
||||||
|
column: x => x.skin_id,
|
||||||
|
principalTable: "skins",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "skin_instances",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
skin_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
condition_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
float_value = table.Column<decimal>(type: "numeric(10,9)", nullable: false),
|
||||||
|
paint_seed = table.Column<string>(type: "text", nullable: false),
|
||||||
|
stat_trak = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
souvenir = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
first_seen_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_skin_instances", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_skin_instances_skin_conditions_condition_id",
|
||||||
|
column: x => x.condition_id,
|
||||||
|
principalTable: "skin_conditions",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_skin_instances_skins_skin_id",
|
||||||
|
column: x => x.skin_id,
|
||||||
|
principalTable: "skins",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "inventory_items",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
user_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
skin_instance_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
asset_id = table.Column<string>(type: "text", nullable: false),
|
||||||
|
acquired_at = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_inventory_items", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_inventory_items_skin_instances_skin_instance_id",
|
||||||
|
column: x => x.skin_instance_id,
|
||||||
|
principalTable: "skin_instances",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_inventory_items_steam_users_user_id",
|
||||||
|
column: x => x.user_id,
|
||||||
|
principalTable: "steam_users",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "trade_items",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
trade_id = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
inventory_item_id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_trade_items", x => x.id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_trade_items_inventory_items_inventory_item_id",
|
||||||
|
column: x => x.inventory_item_id,
|
||||||
|
principalTable: "inventory_items",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "fk_trade_items_trades_trade_id",
|
||||||
|
column: x => x.trade_id,
|
||||||
|
principalTable: "trades",
|
||||||
|
principalColumn: "id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_inventory_items_asset_id",
|
||||||
|
table: "inventory_items",
|
||||||
|
column: "asset_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_inventory_items_skin_instance_id",
|
||||||
|
table: "inventory_items",
|
||||||
|
column: "skin_instance_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_inventory_items_user_id",
|
||||||
|
table: "inventory_items",
|
||||||
|
column: "user_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_price_histories_condition_id",
|
||||||
|
table: "price_histories",
|
||||||
|
column: "condition_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_price_histories_skin_id_condition_id_recorded_at",
|
||||||
|
table: "price_histories",
|
||||||
|
columns: new[] { "skin_id", "condition_id", "recorded_at" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skin_conditions_skin_id",
|
||||||
|
table: "skin_conditions",
|
||||||
|
column: "skin_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skin_instances_condition_id",
|
||||||
|
table: "skin_instances",
|
||||||
|
column: "condition_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skin_instances_float_value",
|
||||||
|
table: "skin_instances",
|
||||||
|
column: "float_value");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skin_instances_paint_seed",
|
||||||
|
table: "skin_instances",
|
||||||
|
column: "paint_seed");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skin_instances_skin_id",
|
||||||
|
table: "skin_instances",
|
||||||
|
column: "skin_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skins_true_float",
|
||||||
|
table: "skins",
|
||||||
|
column: "true_float");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_skins_weapon_id",
|
||||||
|
table: "skins",
|
||||||
|
column: "weapon_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_steam_users_steam_id",
|
||||||
|
table: "steam_users",
|
||||||
|
column: "steam_id",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_trade_items_inventory_item_id",
|
||||||
|
table: "trade_items",
|
||||||
|
column: "inventory_item_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_trade_items_trade_id",
|
||||||
|
table: "trade_items",
|
||||||
|
column: "trade_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_trades_from_user_id",
|
||||||
|
table: "trades",
|
||||||
|
column: "from_user_id");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_trades_to_user_id",
|
||||||
|
table: "trades",
|
||||||
|
column: "to_user_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "price_histories");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "trade_items");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "inventory_items");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "trades");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "skin_instances");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "steam_users");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "skin_conditions");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "skins");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "weapons");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,570 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using BlueLaminate.EFCore.Data;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace BlueLaminate.EFCore.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(SkinTrackerDbContext))]
|
||||||
|
partial class SkinTrackerDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("AcquiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("acquired_at");
|
||||||
|
|
||||||
|
b.Property<string>("AssetId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("asset_id");
|
||||||
|
|
||||||
|
b.Property<int>("SkinInstanceId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_instance_id");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("user_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_inventory_items");
|
||||||
|
|
||||||
|
b.HasIndex("AssetId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_asset_id");
|
||||||
|
|
||||||
|
b.HasIndex("SkinInstanceId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_skin_instance_id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId")
|
||||||
|
.HasDatabaseName("ix_inventory_items_user_id");
|
||||||
|
|
||||||
|
b.ToTable("inventory_items", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.PriceHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ConditionId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("condition_id");
|
||||||
|
|
||||||
|
b.Property<string>("Currency")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("currency");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)")
|
||||||
|
.HasColumnName("price");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("RecordedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("recorded_at");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.Property<string>("Source")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("source");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_price_histories");
|
||||||
|
|
||||||
|
b.HasIndex("ConditionId")
|
||||||
|
.HasDatabaseName("ix_price_histories_condition_id");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId", "ConditionId", "RecordedAt")
|
||||||
|
.HasDatabaseName("ix_price_histories_skin_id_condition_id_recorded_at");
|
||||||
|
|
||||||
|
b.ToTable("price_histories", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("description");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatMax")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(1.0m)
|
||||||
|
.HasColumnName("float_max");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatMin")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasDefaultValue(0.0m)
|
||||||
|
.HasColumnName("float_min");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("image_url");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Rarity")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("rarity");
|
||||||
|
|
||||||
|
b.Property<bool>("TrueFloat")
|
||||||
|
.ValueGeneratedOnAddOrUpdate()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("true_float")
|
||||||
|
.HasComputedColumnSql("float_min = 0.0 AND float_max = 1.0", true);
|
||||||
|
|
||||||
|
b.Property<int>("WeaponId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("weapon_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skins");
|
||||||
|
|
||||||
|
b.HasIndex("TrueFloat")
|
||||||
|
.HasDatabaseName("ix_skins_true_float");
|
||||||
|
|
||||||
|
b.HasIndex("WeaponId")
|
||||||
|
.HasDatabaseName("ix_skins_weapon_id");
|
||||||
|
|
||||||
|
b.ToTable("skins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Condition")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("condition");
|
||||||
|
|
||||||
|
b.Property<decimal>("MaxFloat")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("max_float");
|
||||||
|
|
||||||
|
b.Property<decimal>("MinFloat")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("min_float");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skin_conditions");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId")
|
||||||
|
.HasDatabaseName("ix_skin_conditions_skin_id");
|
||||||
|
|
||||||
|
b.ToTable("skin_conditions", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ConditionId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("condition_id");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("FirstSeenAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("first_seen_at");
|
||||||
|
|
||||||
|
b.Property<decimal>("FloatValue")
|
||||||
|
.HasColumnType("numeric(10,9)")
|
||||||
|
.HasColumnName("float_value");
|
||||||
|
|
||||||
|
b.Property<string>("PaintSeed")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("paint_seed");
|
||||||
|
|
||||||
|
b.Property<int>("SkinId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("skin_id");
|
||||||
|
|
||||||
|
b.Property<bool>("Souvenir")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("souvenir");
|
||||||
|
|
||||||
|
b.Property<bool>("StatTrak")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("stat_trak");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_skin_instances");
|
||||||
|
|
||||||
|
b.HasIndex("ConditionId")
|
||||||
|
.HasDatabaseName("ix_skin_instances_condition_id");
|
||||||
|
|
||||||
|
b.HasIndex("FloatValue")
|
||||||
|
.HasDatabaseName("ix_skin_instances_float_value");
|
||||||
|
|
||||||
|
b.HasIndex("PaintSeed")
|
||||||
|
.HasDatabaseName("ix_skin_instances_paint_seed");
|
||||||
|
|
||||||
|
b.HasIndex("SkinId")
|
||||||
|
.HasDatabaseName("ix_skin_instances_skin_id");
|
||||||
|
|
||||||
|
b.ToTable("skin_instances", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SteamUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("DisplayName")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("display_name");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("LastSyncedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("last_synced_at");
|
||||||
|
|
||||||
|
b.Property<string>("SteamId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("steam_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_steam_users");
|
||||||
|
|
||||||
|
b.HasIndex("SteamId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_steam_users_steam_id");
|
||||||
|
|
||||||
|
b.ToTable("steam_users", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("FromUserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("from_user_id");
|
||||||
|
|
||||||
|
b.Property<string>("SteamTradeId")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("steam_trade_id");
|
||||||
|
|
||||||
|
b.Property<int>("ToUserId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("to_user_id");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("TradedAt")
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasColumnName("traded_at");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_trades");
|
||||||
|
|
||||||
|
b.HasIndex("FromUserId")
|
||||||
|
.HasDatabaseName("ix_trades_from_user_id");
|
||||||
|
|
||||||
|
b.HasIndex("ToUserId")
|
||||||
|
.HasDatabaseName("ix_trades_to_user_id");
|
||||||
|
|
||||||
|
b.ToTable("trades", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.TradeItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("InventoryItemId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("inventory_item_id");
|
||||||
|
|
||||||
|
b.Property<int>("TradeId")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("trade_id");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_trade_items");
|
||||||
|
|
||||||
|
b.HasIndex("InventoryItemId")
|
||||||
|
.HasDatabaseName("ix_trade_items_inventory_item_id");
|
||||||
|
|
||||||
|
b.HasIndex("TradeId")
|
||||||
|
.HasDatabaseName("ix_trade_items_trade_id");
|
||||||
|
|
||||||
|
b.ToTable("trade_items", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Weapon", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("name");
|
||||||
|
|
||||||
|
b.Property<string>("Team")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("team");
|
||||||
|
|
||||||
|
b.Property<string>("Type")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("type");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_weapons");
|
||||||
|
|
||||||
|
b.ToTable("weapons", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinInstance", "SkinInstance")
|
||||||
|
.WithMany("InventoryItems")
|
||||||
|
.HasForeignKey("SkinInstanceId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_inventory_items_skin_instances_skin_instance_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "User")
|
||||||
|
.WithMany("InventoryItems")
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_inventory_items_steam_users_user_id");
|
||||||
|
|
||||||
|
b.Navigation("SkinInstance");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.PriceHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
|
||||||
|
.WithMany("PriceHistories")
|
||||||
|
.HasForeignKey("ConditionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_price_histories_skin_conditions_condition_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("PriceHistories")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_price_histories_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Condition");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Weapon", "Weapon")
|
||||||
|
.WithMany("Skins")
|
||||||
|
.HasForeignKey("WeaponId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skins_weapons_weapon_id");
|
||||||
|
|
||||||
|
b.Navigation("Weapon");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("Conditions")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_conditions_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SkinCondition", "Condition")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("ConditionId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_instances_skin_conditions_condition_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Skin", "Skin")
|
||||||
|
.WithMany("Instances")
|
||||||
|
.HasForeignKey("SkinId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_skin_instances_skins_skin_id");
|
||||||
|
|
||||||
|
b.Navigation("Condition");
|
||||||
|
|
||||||
|
b.Navigation("Skin");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "FromUser")
|
||||||
|
.WithMany("TradesSent")
|
||||||
|
.HasForeignKey("FromUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trades_steam_users_from_user_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.SteamUser", "ToUser")
|
||||||
|
.WithMany("TradesReceived")
|
||||||
|
.HasForeignKey("ToUserId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trades_steam_users_to_user_id");
|
||||||
|
|
||||||
|
b.Navigation("FromUser");
|
||||||
|
|
||||||
|
b.Navigation("ToUser");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.TradeItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.InventoryItem", "InventoryItem")
|
||||||
|
.WithMany("TradeItems")
|
||||||
|
.HasForeignKey("InventoryItemId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trade_items_inventory_items_inventory_item_id");
|
||||||
|
|
||||||
|
b.HasOne("BlueLaminate.EFCore.Entities.Trade", "Trade")
|
||||||
|
.WithMany("TradeItems")
|
||||||
|
.HasForeignKey("TradeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired()
|
||||||
|
.HasConstraintName("fk_trade_items_trades_trade_id");
|
||||||
|
|
||||||
|
b.Navigation("InventoryItem");
|
||||||
|
|
||||||
|
b.Navigation("Trade");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("TradeItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Skin", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Conditions");
|
||||||
|
|
||||||
|
b.Navigation("Instances");
|
||||||
|
|
||||||
|
b.Navigation("PriceHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinCondition", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Instances");
|
||||||
|
|
||||||
|
b.Navigation("PriceHistories");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SkinInstance", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("InventoryItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.SteamUser", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("InventoryItems");
|
||||||
|
|
||||||
|
b.Navigation("TradesReceived");
|
||||||
|
|
||||||
|
b.Navigation("TradesSent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Trade", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("TradeItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("BlueLaminate.EFCore.Entities.Weapon", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Skins");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
BlueLaminate/BlueLaminate.EFCore/Program.cs
Normal file
7
BlueLaminate/BlueLaminate.EFCore/Program.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using BlueLaminate.EFCore.Data;
|
||||||
|
|
||||||
|
// Build the context the same way the design-time factory does. Run
|
||||||
|
// `dotnet ef database update` to apply migrations to the configured database.
|
||||||
|
using var db = new SkinTrackerDbContextFactory().CreateDbContext(args);
|
||||||
|
|
||||||
|
Console.WriteLine($"CS2 Skin Tracker — {db.Model.GetEntityTypes().Count()} entities mapped.");
|
||||||
3
BlueLaminate/BlueLaminate.slnx
Normal file
3
BlueLaminate/BlueLaminate.slnx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="BlueLaminate.EFCore/BlueLaminate.EFCore.csproj" />
|
||||||
|
</Solution>
|
||||||
54
WeaponGrabber/WeaponScraper.py
Normal file
54
WeaponGrabber/WeaponScraper.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
"""Print every CS2 weapon listed on the Counter-Strike wiki.
|
||||||
|
|
||||||
|
Requires: pip install curl_cffi beautifulsoup4
|
||||||
|
|
||||||
|
Uses curl_cffi instead of requests because the wiki sits behind Cloudflare,
|
||||||
|
which blocks Python's default TLS fingerprint with a 403 even when the
|
||||||
|
User-Agent header looks like a browser.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from curl_cffi import requests
|
||||||
|
|
||||||
|
URL = "https://counterstrike.fandom.com/wiki/Weapons"
|
||||||
|
TAB_HASH = "Global_Offensive_&_Counter-Strike_2"
|
||||||
|
ANNOTATION_RE = re.compile(r"\s*\((?:CT|T)\)\s*$")
|
||||||
|
STOCK_PREFIX_RE = re.compile(r"^Stock\s+")
|
||||||
|
|
||||||
|
|
||||||
|
def cs2_weapons():
|
||||||
|
resp = requests.get(URL, impersonate="chrome", timeout=30)
|
||||||
|
resp.raise_for_status()
|
||||||
|
soup = BeautifulSoup(resp.text, "html.parser")
|
||||||
|
|
||||||
|
weapons, seen = [], set()
|
||||||
|
for tabber in soup.select("div.tabber"):
|
||||||
|
tabs = tabber.select("li.wds-tabs__tab")
|
||||||
|
idx = next(
|
||||||
|
(i for i, t in enumerate(tabs) if t.get("data-hash") == TAB_HASH),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
if idx is None:
|
||||||
|
continue
|
||||||
|
contents = tabber.find_all("div", class_="wds-tab__content")
|
||||||
|
if idx >= len(contents):
|
||||||
|
continue
|
||||||
|
for cap in contents[idx].select("div.lightbox-caption"):
|
||||||
|
name = cap.get_text(" ", strip=True)
|
||||||
|
name = ANNOTATION_RE.sub("", name)
|
||||||
|
name = STOCK_PREFIX_RE.sub("", name).strip()
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
if name not in seen:
|
||||||
|
seen.add(name)
|
||||||
|
weapons.append(name)
|
||||||
|
return weapons
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
weaps = cs2_weapons()
|
||||||
|
for w in weaps:
|
||||||
|
print(w)
|
||||||
|
|
||||||
|
print(len(weaps))
|
||||||
Reference in New Issue
Block a user