Adding upkeep
This commit is contained in:
@@ -284,6 +284,7 @@ public class LocationService
|
||||
public async Task<Location?> AssignWorkerAsync(string username, AssignWorkerRequest request)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
await CompletePendingWorkerAssignmentsAsync(username);
|
||||
var location = await GetAsync(request.Q, request.R);
|
||||
if (location is null ||
|
||||
!string.Equals(location.OwnerUsername, username, StringComparison.OrdinalIgnoreCase) ||
|
||||
@@ -308,36 +309,19 @@ public class LocationService
|
||||
var claimed = await _units.UpdateOneAsync(
|
||||
x => x.Id == unit.Id && x.Status == "Idle",
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Q, request.Q)
|
||||
.Set(x => x.R, request.R)
|
||||
.Set(x => x.Status, "Working")
|
||||
.Set(x => x.Status, "MovingToWork")
|
||||
.Set(x => x.MovementRemaining, 0)
|
||||
.Set(x => x.DestinationQ, request.Q)
|
||||
.Set(x => x.DestinationR, request.R)
|
||||
.Set(x => x.MovementStartedAtUtc, now)
|
||||
.Set(x => x.MovementCompletesAtUtc, now.AddMinutes(Math.Max(1, HexDistance(unit.Q, unit.R, request.Q, request.R))))
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
if (claimed.ModifiedCount == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var updated = await _locations.FindOneAndUpdateAsync(
|
||||
x => x.Id == location.Id && (x.WorkerUnitId == null || x.WorkerUnitId == ""),
|
||||
Builders<Location>.Update
|
||||
.Set(x => x.WorkerUnitId, unit.Id)
|
||||
.Set(x => x.WorkerUnitType, "Peasant")
|
||||
.Set(x => x.LastResourceGeneratedAtUtc, now)
|
||||
.Set(x => x.UpdatedAtUtc, now),
|
||||
new FindOneAndUpdateOptions<Location> { ReturnDocument = ReturnDocument.After });
|
||||
|
||||
if (updated is null)
|
||||
{
|
||||
await _units.UpdateOneAsync(
|
||||
x => x.Id == unit.Id,
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Status, "Idle")
|
||||
.Set(x => x.UpdatedAtUtc, DateTime.UtcNow));
|
||||
return null;
|
||||
}
|
||||
|
||||
await RecalculateWorkerGenerationAsync(username);
|
||||
return updated;
|
||||
return location;
|
||||
}
|
||||
|
||||
public async Task<Location?> DeassignWorkerAsync(string username, DeassignWorkerRequest request)
|
||||
@@ -433,6 +417,7 @@ public class LocationService
|
||||
public async Task<List<LocationResponse>> GetVisibleAsync(string username, int? visibilityDepth = null)
|
||||
{
|
||||
await CompleteFinishedBuildingsAsync(username);
|
||||
await CompletePendingWorkerAssignmentsAsync(username);
|
||||
await RecalculateWorkerGenerationAsync(username);
|
||||
|
||||
var ownedLocations = await _locations.Find(x => x.OwnerUsername == username).ToListAsync();
|
||||
@@ -500,6 +485,7 @@ public class LocationService
|
||||
|
||||
public async Task<LocationResponse?> GetVisibleLocationAsync(string username, int q, int r)
|
||||
{
|
||||
await CompletePendingWorkerAssignmentsAsync(username);
|
||||
if (!await CanSeeAsync(username, q, r))
|
||||
{
|
||||
return null;
|
||||
@@ -522,6 +508,98 @@ public class LocationService
|
||||
return generated.Count == 0 ? null : LocationResponse.FromLocation(generated[0]);
|
||||
}
|
||||
|
||||
private async Task CompletePendingWorkerAssignmentsAsync(string username)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var movingWorkers = await _units.Find(x =>
|
||||
x.Username == username &&
|
||||
x.UnitType == "Peasant" &&
|
||||
x.Status == "MovingToWork" &&
|
||||
x.MovementCompletesAtUtc != null &&
|
||||
x.MovementCompletesAtUtc <= now)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var worker in movingWorkers)
|
||||
{
|
||||
if (worker.DestinationQ is null || worker.DestinationR is null)
|
||||
{
|
||||
await _units.UpdateOneAsync(
|
||||
x => x.Id == worker.Id,
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Status, "Idle")
|
||||
.Unset(x => x.MovementStartedAtUtc)
|
||||
.Unset(x => x.MovementCompletesAtUtc)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
continue;
|
||||
}
|
||||
|
||||
var destinationQ = worker.DestinationQ.Value;
|
||||
var destinationR = worker.DestinationR.Value;
|
||||
var currentQ = worker.Q;
|
||||
var currentR = worker.R;
|
||||
var nextTick = worker.MovementCompletesAtUtc!.Value;
|
||||
while (nextTick <= now && HexDistance(currentQ, currentR, destinationQ, destinationR) > 1)
|
||||
{
|
||||
(currentQ, currentR) = NextStepToward(currentQ, currentR, destinationQ, destinationR);
|
||||
nextTick = nextTick.AddMinutes(1);
|
||||
}
|
||||
|
||||
if (HexDistance(currentQ, currentR, destinationQ, destinationR) > 1)
|
||||
{
|
||||
await _units.UpdateOneAsync(
|
||||
x => x.Id == worker.Id,
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Q, currentQ)
|
||||
.Set(x => x.R, currentR)
|
||||
.Set(x => x.MovementCompletesAtUtc, nextTick)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
continue;
|
||||
}
|
||||
|
||||
var location = await _locations.FindOneAndUpdateAsync(
|
||||
x => x.OwnerUsername == username &&
|
||||
x.Q == destinationQ &&
|
||||
x.R == destinationR &&
|
||||
!string.IsNullOrWhiteSpace(x.BuildingType) &&
|
||||
x.BuildingStatus != "Building" &&
|
||||
(x.WorkerUnitId == null || x.WorkerUnitId == ""),
|
||||
Builders<Location>.Update
|
||||
.Set(x => x.WorkerUnitId, worker.Id)
|
||||
.Set(x => x.WorkerUnitType, "Peasant")
|
||||
.Set(x => x.LastResourceGeneratedAtUtc, now)
|
||||
.Set(x => x.UpdatedAtUtc, now),
|
||||
new FindOneAndUpdateOptions<Location> { ReturnDocument = ReturnDocument.After });
|
||||
|
||||
var status = location is null ? "Idle" : "Working";
|
||||
await _units.UpdateOneAsync(
|
||||
x => x.Id == worker.Id,
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Q, destinationQ)
|
||||
.Set(x => x.R, destinationR)
|
||||
.Set(x => x.Status, status)
|
||||
.Set(x => x.LastMovementRefillAtUtc, now)
|
||||
.Unset(x => x.DestinationQ)
|
||||
.Unset(x => x.DestinationR)
|
||||
.Unset(x => x.MovementStartedAtUtc)
|
||||
.Unset(x => x.MovementCompletesAtUtc)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
}
|
||||
|
||||
if (movingWorkers.Count > 0)
|
||||
{
|
||||
await RecalculateWorkerGenerationAsync(username);
|
||||
}
|
||||
}
|
||||
|
||||
private static (int q, int r) NextStepToward(int fromQ, int fromR, int toQ, int toR)
|
||||
{
|
||||
return NeighborCoordinates(fromQ, fromR)
|
||||
.OrderBy(x => HexDistance(x.Q, x.R, toQ, toR))
|
||||
.ThenBy(x => x.Q)
|
||||
.ThenBy(x => x.R)
|
||||
.First();
|
||||
}
|
||||
|
||||
public async Task<bool> CanSeeAsync(string username, int q, int r)
|
||||
{
|
||||
var ownedLocations = await _locations.Find(x => x.OwnerUsername == username).ToListAsync();
|
||||
|
||||
Reference in New Issue
Block a user