Adding units
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user