NEW FEATURES:
- Daily login rewards with Gold and Cash
- Daily time trial racing events
- FREE gold purchase system
- Streak tracking for consecutive days
- Web panel for managing rewards and events
ENDPOINTS ADDED:
- GET/POST /synergy/rewards/daily/{id} - Daily rewards
- POST /synergy/rewards/gold/purchase - Buy gold (FREE)
- GET /synergy/rewards/timetrials - Active events
- POST /synergy/rewards/timetrials/{id}/submit - Submit times
DATABASE:
- DailyReward table - tracks claims and streaks
- TimeTrial table - racing events with rewards
- TimeTrialResult table - player submissions
- User.Gold and User.Cash - currency tracking
WEB PANEL:
- /admin/rewards - Manage all reward features
- Create/edit/activate time trial events
- View reward statistics and history
- Gold packages in catalog (100, 500, 1000, 5000)
FOCUS:
- Single-player progression features
- NO race teams or multiplayer
- Perfect for offline play
- All purchases are FREE in community server
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
220 lines
6.7 KiB
C#
220 lines
6.7 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace RR3CommunityServer.Data;
|
|
|
|
public class RR3DbContext : DbContext
|
|
{
|
|
public RR3DbContext(DbContextOptions<RR3DbContext> options) : base(options) { }
|
|
|
|
public DbSet<Device> Devices { get; set; }
|
|
public DbSet<User> Users { get; set; }
|
|
public DbSet<Session> Sessions { get; set; }
|
|
public DbSet<Purchase> Purchases { get; set; }
|
|
public DbSet<CatalogItem> CatalogItems { get; set; }
|
|
public DbSet<DailyReward> DailyRewards { get; set; }
|
|
public DbSet<TimeTrial> TimeTrials { get; set; }
|
|
public DbSet<TimeTrialResult> TimeTrialResults { get; set; }
|
|
|
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
|
{
|
|
base.OnModelCreating(modelBuilder);
|
|
|
|
// Seed some default catalog items
|
|
modelBuilder.Entity<CatalogItem>().HasData(
|
|
new CatalogItem
|
|
{
|
|
Id = 1,
|
|
Sku = "com.ea.rr3.gold_1000",
|
|
Name = "1000 Gold",
|
|
Type = "currency",
|
|
Price = 0.99m,
|
|
Available = true
|
|
},
|
|
new CatalogItem
|
|
{
|
|
Id = 2,
|
|
Sku = "com.ea.rr3.car_tier1",
|
|
Name = "Starter Car",
|
|
Type = "car",
|
|
Price = 0m,
|
|
Available = true
|
|
},
|
|
new CatalogItem
|
|
{
|
|
Id = 3,
|
|
Sku = "com.ea.rr3.upgrade_engine",
|
|
Name = "Engine Upgrade",
|
|
Type = "upgrade",
|
|
Price = 4.99m,
|
|
Available = true
|
|
}
|
|
);
|
|
|
|
// Seed gold purchase options
|
|
modelBuilder.Entity<CatalogItem>().HasData(
|
|
new CatalogItem
|
|
{
|
|
Id = 4,
|
|
Sku = "com.ea.rr3.gold_100",
|
|
Name = "100 Gold",
|
|
Type = "currency",
|
|
Price = 0m, // FREE in community server
|
|
Available = true
|
|
},
|
|
new CatalogItem
|
|
{
|
|
Id = 5,
|
|
Sku = "com.ea.rr3.gold_500",
|
|
Name = "500 Gold",
|
|
Type = "currency",
|
|
Price = 0m,
|
|
Available = true
|
|
},
|
|
new CatalogItem
|
|
{
|
|
Id = 6,
|
|
Sku = "com.ea.rr3.gold_1000",
|
|
Name = "1000 Gold",
|
|
Type = "currency",
|
|
Price = 0m,
|
|
Available = true
|
|
},
|
|
new CatalogItem
|
|
{
|
|
Id = 7,
|
|
Sku = "com.ea.rr3.gold_5000",
|
|
Name = "5000 Gold",
|
|
Type = "currency",
|
|
Price = 0m,
|
|
Available = true
|
|
}
|
|
);
|
|
|
|
// Seed time trials
|
|
modelBuilder.Entity<TimeTrial>().HasData(
|
|
new TimeTrial
|
|
{
|
|
Id = 1,
|
|
Name = "Daily Sprint Challenge",
|
|
TrackName = "Silverstone National",
|
|
CarName = "Any Car",
|
|
StartDate = DateTime.UtcNow,
|
|
EndDate = DateTime.UtcNow.AddDays(7),
|
|
TargetTime = 90.5,
|
|
GoldReward = 50,
|
|
CashReward = 10000,
|
|
Active = true
|
|
},
|
|
new TimeTrial
|
|
{
|
|
Id = 2,
|
|
Name = "Speed Demon Trial",
|
|
TrackName = "Dubai Autodrome",
|
|
CarName = "Any Car",
|
|
StartDate = DateTime.UtcNow,
|
|
EndDate = DateTime.UtcNow.AddDays(7),
|
|
TargetTime = 120.0,
|
|
GoldReward = 100,
|
|
CashReward = 25000,
|
|
Active = true
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
// Database entities
|
|
public class Device
|
|
{
|
|
public int Id { get; set; }
|
|
public string DeviceId { get; set; } = string.Empty;
|
|
public string HardwareId { get; set; } = string.Empty;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime LastSeenAt { get; set; } = DateTime.UtcNow;
|
|
}
|
|
|
|
public class User
|
|
{
|
|
public int Id { get; set; }
|
|
public string SynergyId { get; set; } = string.Empty;
|
|
public string? DeviceId { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public string? Nickname { get; set; }
|
|
public int? Gold { get; set; } = 0;
|
|
public int? Cash { get; set; } = 0;
|
|
}
|
|
|
|
public class Session
|
|
{
|
|
public int Id { get; set; }
|
|
public string SessionId { get; set; } = string.Empty;
|
|
public string? SynergyId { get; set; }
|
|
public string DeviceId { get; set; } = string.Empty;
|
|
public int? UserId { get; set; }
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public DateTime ExpiresAt { get; set; }
|
|
}
|
|
|
|
public class Purchase
|
|
{
|
|
public int Id { get; set; }
|
|
public string SynergyId { get; set; } = string.Empty;
|
|
public string ItemId { get; set; } = string.Empty;
|
|
public string Sku { get; set; } = string.Empty;
|
|
public string OrderId { get; set; } = string.Empty;
|
|
public DateTime PurchaseTime { get; set; } = DateTime.UtcNow;
|
|
public string Token { get; set; } = string.Empty;
|
|
public decimal Price { get; set; }
|
|
public string Status { get; set; } = "approved";
|
|
// For web panel display
|
|
public int? UserId { get; set; }
|
|
public DateTime PurchaseDate => PurchaseTime;
|
|
}
|
|
|
|
public class CatalogItem
|
|
{
|
|
public int Id { get; set; }
|
|
public string Sku { get; set; } = string.Empty;
|
|
public string Name { get; set; } = string.Empty;
|
|
public string Type { get; set; } = string.Empty;
|
|
public decimal Price { get; set; }
|
|
public bool Available { get; set; } = true;
|
|
}
|
|
|
|
public class DailyReward
|
|
{
|
|
public int Id { get; set; }
|
|
public int UserId { get; set; }
|
|
public DateTime RewardDate { get; set; }
|
|
public int GoldAmount { get; set; }
|
|
public int CashAmount { get; set; }
|
|
public bool Claimed { get; set; }
|
|
public DateTime? ClaimedAt { get; set; }
|
|
public int Streak { get; set; }
|
|
}
|
|
|
|
public class TimeTrial
|
|
{
|
|
public int Id { get; set; }
|
|
public string Name { get; set; } = string.Empty;
|
|
public string TrackName { get; set; } = string.Empty;
|
|
public string CarName { get; set; } = string.Empty;
|
|
public DateTime StartDate { get; set; }
|
|
public DateTime EndDate { get; set; }
|
|
public double TargetTime { get; set; }
|
|
public int GoldReward { get; set; }
|
|
public int CashReward { get; set; }
|
|
public bool Active { get; set; } = true;
|
|
}
|
|
|
|
public class TimeTrialResult
|
|
{
|
|
public int Id { get; set; }
|
|
public int UserId { get; set; }
|
|
public int TimeTrialId { get; set; }
|
|
public double TimeSeconds { get; set; }
|
|
public DateTime SubmittedAt { get; set; }
|
|
public bool BeatTarget { get; set; }
|
|
public int GoldEarned { get; set; }
|
|
public int CashEarned { get; set; }
|
|
}
|