Adding login screen, hex grid, and location service
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
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"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user