Files
territory-autobattler/microservices/LocationsApi/Services/LocationService.cs
T

92 lines
3.1 KiB
C#

using LocationsApi.Models;
using MongoDB.Driver;
namespace LocationsApi.Services;
public class LocationService
{
private readonly IMongoCollection<Location> _locations;
public LocationService(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);
_locations = database.GetCollection<Location>("Locations");
var coordinateIndex = Builders<Location>.IndexKeys
.Ascending(x => x.Q)
.Ascending(x => x.R);
_locations.Indexes.CreateOne(new CreateIndexModel<Location>(
coordinateIndex,
new CreateIndexOptions { Unique = true }));
}
public Task<List<Location>> GetAllAsync() =>
_locations.Find(FilterDefinition<Location>.Empty)
.SortBy(x => x.Q)
.ThenBy(x => x.R)
.ToListAsync();
public Task<List<Location>> GetRangeAsync(int minQ, int maxQ, int minR, int maxR) =>
_locations.Find(x => x.Q >= minQ && x.Q <= maxQ && x.R >= minR && x.R <= maxR)
.SortBy(x => x.Q)
.ThenBy(x => x.R)
.ToListAsync();
public async Task<Location?> GetAsync(int q, int r) =>
await _locations.Find(x => x.Q == q && x.R == r).FirstOrDefaultAsync();
public async Task<Location> UpsertAsync(UpsertLocationRequest request, string? ownerUsername = null)
{
var now = DateTime.UtcNow;
var update = Builders<Location>.Update
.SetOnInsert(x => x.CreatedAtUtc, now)
.Set(x => x.Terrain, NormalizeTerrain(request.Terrain))
.Set(x => x.Label, request.Label)
.Set(x => x.Level, Math.Max(1, request.Level))
.Set(x => x.UpdatedAtUtc, now);
if (!string.IsNullOrWhiteSpace(ownerUsername))
{
update = update.Set(x => x.OwnerUsername, ownerUsername);
}
var options = new FindOneAndUpdateOptions<Location>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After
};
return await _locations.FindOneAndUpdateAsync(
x => x.Q == request.Q && x.R == request.R,
update,
options);
}
public async Task<Location> ClaimAsync(int q, int r, string username)
{
var existing = await GetAsync(q, r);
if (existing is not null)
{
existing.OwnerUsername = username;
existing.UpdatedAtUtc = DateTime.UtcNow;
await _locations.ReplaceOneAsync(x => x.Id == existing.Id, existing);
return existing;
}
return await UpsertAsync(new UpsertLocationRequest { Q = q, R = r, Terrain = "Field" }, username);
}
private static string NormalizeTerrain(string terrain)
{
var trimmed = terrain.Trim();
return trimmed switch
{
"Command" or "Field" or "Forest" or "Ore" or "Highland" => trimmed,
_ => "Field"
};
}
}