adding resources
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using LocationsApi.Models;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace LocationsApi.Services;
|
||||
|
||||
public class ResourceService
|
||||
{
|
||||
private readonly IMongoCollection<PlayerResources> _resources;
|
||||
private readonly int _startingGold;
|
||||
private readonly int _headquartersGoldPerMinute;
|
||||
|
||||
public ResourceService(IConfiguration cfg)
|
||||
{
|
||||
var connectionString = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017";
|
||||
var databaseName = cfg["MongoDB:DatabaseName"] ?? "territory-autobattler";
|
||||
var client = new MongoClient(connectionString);
|
||||
var database = client.GetDatabase(databaseName);
|
||||
_resources = database.GetCollection<PlayerResources>("PlayerResources");
|
||||
_startingGold = int.TryParse(cfg["Resources:StartingGold"], out var startingGold) ? Math.Max(0, startingGold) : 100;
|
||||
_headquartersGoldPerMinute = int.TryParse(cfg["Resources:HeadquartersGoldPerMinute"], out var goldPerMinute)
|
||||
? Math.Max(0, goldPerMinute)
|
||||
: 10;
|
||||
|
||||
_resources.Indexes.CreateOne(new CreateIndexModel<PlayerResources>(
|
||||
Builders<PlayerResources>.IndexKeys.Ascending(x => x.Username),
|
||||
new CreateIndexOptions { Unique = true }));
|
||||
}
|
||||
|
||||
public async Task<PlayerResources> EnsureAsync(string username)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var update = Builders<PlayerResources>.Update
|
||||
.SetOnInsert(x => x.Username, username)
|
||||
.SetOnInsert(x => x.Gold, _startingGold)
|
||||
.SetOnInsert(x => x.CreatedAtUtc, now)
|
||||
.SetOnInsert(x => x.LastGoldGeneratedAtUtc, now)
|
||||
.Set(x => x.GoldPerMinute, _headquartersGoldPerMinute)
|
||||
.Set(x => x.UpdatedAtUtc, now);
|
||||
|
||||
var resources = await _resources.FindOneAndUpdateAsync(
|
||||
x => x.Username == username,
|
||||
update,
|
||||
new FindOneAndUpdateOptions<PlayerResources>
|
||||
{
|
||||
IsUpsert = true,
|
||||
ReturnDocument = ReturnDocument.After
|
||||
});
|
||||
|
||||
return await ApplyGoldGenerationAsync(resources);
|
||||
}
|
||||
|
||||
public async Task<PlayerResources> GetAsync(string username)
|
||||
{
|
||||
var resources = await EnsureAsync(username);
|
||||
return await ApplyGoldGenerationAsync(resources);
|
||||
}
|
||||
|
||||
private async Task<PlayerResources> ApplyGoldGenerationAsync(PlayerResources resources)
|
||||
{
|
||||
if (resources.GoldPerMinute <= 0)
|
||||
{
|
||||
return resources;
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var elapsed = now - resources.LastGoldGeneratedAtUtc;
|
||||
var elapsedMinutes = (int)Math.Floor(elapsed.TotalMinutes);
|
||||
if (elapsedMinutes <= 0)
|
||||
{
|
||||
return resources;
|
||||
}
|
||||
|
||||
var generatedGold = elapsedMinutes * resources.GoldPerMinute;
|
||||
var generationTimestamp = resources.LastGoldGeneratedAtUtc.AddMinutes(elapsedMinutes);
|
||||
var update = Builders<PlayerResources>.Update
|
||||
.Inc(x => x.Gold, generatedGold)
|
||||
.Set(x => x.GoldPerMinute, _headquartersGoldPerMinute)
|
||||
.Set(x => x.LastGoldGeneratedAtUtc, generationTimestamp)
|
||||
.Set(x => x.UpdatedAtUtc, now);
|
||||
|
||||
return await _resources.FindOneAndUpdateAsync(
|
||||
x => x.Username == resources.Username,
|
||||
update,
|
||||
new FindOneAndUpdateOptions<PlayerResources>
|
||||
{
|
||||
ReturnDocument = ReturnDocument.After
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user