Files
territory-autobattler/microservices/LocationsApi/Services/UnitTrainingService.cs
T
2026-05-18 15:30:46 -05:00

94 lines
3.3 KiB
C#

using LocationsApi.Models;
using MongoDB.Driver;
namespace LocationsApi.Services;
public class UnitTrainingService
{
private const string ScoutUnitType = "Scout";
private readonly IMongoCollection<UnitTraining> _training;
private readonly ResourceService _resources;
private readonly int _scoutGoldCost;
private readonly int _scoutTrainingSeconds;
public UnitTrainingService(IConfiguration cfg, ResourceService resources)
{
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);
_training = database.GetCollection<UnitTraining>("UnitTraining");
_resources = resources;
_scoutGoldCost = int.TryParse(cfg["Units:ScoutGoldCost"], out var scoutGoldCost) ? Math.Max(0, scoutGoldCost) : 50;
_scoutTrainingSeconds = int.TryParse(cfg["Units:ScoutTrainingSeconds"], out var scoutTrainingSeconds)
? Math.Max(1, scoutTrainingSeconds)
: 60;
_training.Indexes.CreateOne(new CreateIndexModel<UnitTraining>(
Builders<UnitTraining>.IndexKeys.Ascending(x => x.Username).Ascending(x => x.Status)));
}
public async Task<PlayerUnitsResponse> GetMineAsync(string username)
{
await CompleteFinishedTrainingAsync(username);
var all = await _training.Find(x => x.Username == username).ToListAsync();
var completedScouts = all.Count(x => x.UnitType == ScoutUnitType && x.Status == "Completed");
var activeTraining = all
.Where(x => x.Status == "Training")
.OrderBy(x => x.CompletesAtUtc)
.Select(UnitTrainingResponse.FromTraining)
.ToList();
return new PlayerUnitsResponse
{
CompletedScouts = completedScouts,
Training = activeTraining
};
}
public async Task<UnitTraining?> TrainAsync(string username, string unitType)
{
if (!string.Equals(unitType, ScoutUnitType, StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException("Unsupported unit type.", nameof(unitType));
}
var spent = await _resources.TrySpendGoldAsync(username, _scoutGoldCost);
if (!spent)
{
return null;
}
var now = DateTime.UtcNow;
var training = new UnitTraining
{
Username = username,
UnitType = ScoutUnitType,
GoldCost = _scoutGoldCost,
Status = "Training",
StartedAtUtc = now,
CompletesAtUtc = now.AddSeconds(_scoutTrainingSeconds),
CreatedAtUtc = now,
UpdatedAtUtc = now
};
await _training.InsertOneAsync(training);
return training;
}
private async Task CompleteFinishedTrainingAsync(string username)
{
var now = DateTime.UtcNow;
var update = Builders<UnitTraining>.Update
.Set(x => x.Status, "Completed")
.Set(x => x.CompletedAtUtc, now)
.Set(x => x.UpdatedAtUtc, now);
await _training.UpdateManyAsync(
x => x.Username == username && x.Status == "Training" && x.CompletesAtUtc <= now,
update);
}
}