From 5f1a4f0b5d84f9e15e4669c87d189dc1d8766a2b Mon Sep 17 00:00:00 2001 From: Killer Date: Sat, 21 Feb 2026 00:01:36 +0100 Subject: [PATCH] Refactor and improve ExpeditionWorker logic --- TBot/Workers/ExpeditionsWorker.cs | 423 ++++++++++++++++++------------ 1 file changed, 252 insertions(+), 171 deletions(-) diff --git a/TBot/Workers/ExpeditionsWorker.cs b/TBot/Workers/ExpeditionsWorker.cs index bcfa777f..ee18ad97 100644 --- a/TBot/Workers/ExpeditionsWorker.cs +++ b/TBot/Workers/ExpeditionsWorker.cs @@ -34,7 +34,7 @@ public ExpeditionsWorker(ITBotMain parentInstance, } public override bool IsWorkerEnabledBySettings() { try { - return (bool) _tbotInstance.InstanceSettings.Expeditions.Active; + return (bool)_tbotInstance.InstanceSettings.Expeditions.Active; } catch (Exception) { return false; } @@ -49,18 +49,25 @@ public override Feature GetFeature() { public override LogSender GetLogSender() { return LogSender.Expeditions; } - - + private int CountActiveExpeditionsFromOrigin(Celestial origin) { + return _tbotInstance.UserData.fleets.Count(f => + f.Mission == Missions.Expedition && + f.Origin != null && + f.Origin.Galaxy == origin.Coordinate.Galaxy && + f.Origin.System == origin.Coordinate.System && + f.Origin.Position == origin.Coordinate.Position && + (int)f.Origin.Type == (int)origin.Coordinate.Type + ); +} protected override async Task Execute() { bool stop = false; bool delay = false; try { - // Wait for the thread semaphore to avoid the concurrency with itself long interval; DateTime time; DateTime newTime; - if ((bool) _tbotInstance.InstanceSettings.Expeditions.Active) { + if ((bool)_tbotInstance.InstanceSettings.Expeditions.Active) { _tbotInstance.UserData.researches = await _tbotOgameBridge.UpdateResearches(); if (_tbotInstance.UserData.researches.Astrophysics == 0) { DoLog(LogLevel.Information, "Skipping: Astrophysics not yet researched!"); @@ -75,44 +82,54 @@ protected override async Task Execute() { _tbotInstance.UserData.slots = await _tbotOgameBridge.UpdateSlots(); _tbotInstance.UserData.fleets = await _fleetScheduler.UpdateFleets(); _tbotInstance.UserData.serverData = await _ogameService.GetServerData(); + List rankSlotsPriority = new() { new RankSlotsPriority(Feature.BrainAutoMine, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.Brain, - ((bool) _tbotInstance.InstanceSettings.Brain.Active && (bool) _tbotInstance.InstanceSettings.Brain.Transports.Active && ((bool) _tbotInstance.InstanceSettings.Brain.AutoMine.Active || (bool) _tbotInstance.InstanceSettings.Brain.AutoResearch.Active || (bool) _tbotInstance.InstanceSettings.Brain.LifeformAutoMine.Active || (bool) _tbotInstance.InstanceSettings.Brain.LifeformAutoResearch.Active)), - (int) _tbotInstance.InstanceSettings.Brain.Transports.MaxSlots, - (int) _tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Transport)), + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.Brain, + ((bool)_tbotInstance.InstanceSettings.Brain.Active && (bool)_tbotInstance.InstanceSettings.Brain.Transports.Active && + ((bool)_tbotInstance.InstanceSettings.Brain.AutoMine.Active || + (bool)_tbotInstance.InstanceSettings.Brain.AutoResearch.Active || + (bool)_tbotInstance.InstanceSettings.Brain.LifeformAutoMine.Active || + (bool)_tbotInstance.InstanceSettings.Brain.LifeformAutoResearch.Active)), + (int)_tbotInstance.InstanceSettings.Brain.Transports.MaxSlots, + (int)_tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Transport)), new RankSlotsPriority(Feature.Expeditions, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.Expeditions, - (bool) _tbotInstance.InstanceSettings.Expeditions.Active, - (int) _tbotInstance.UserData.slots.ExpTotal, + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.Expeditions, + (bool)_tbotInstance.InstanceSettings.Expeditions.Active, + (int)_tbotInstance.UserData.slots.ExpTotal, (int)_tbotInstance.UserData.slots.ExpInUse), new RankSlotsPriority(Feature.AutoFarm, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoFarm, - (bool) _tbotInstance.InstanceSettings.AutoFarm.Active, - (int) _tbotInstance.InstanceSettings.AutoFarm.MaxSlots, - (int) _tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Attack)), + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoFarm, + (bool)_tbotInstance.InstanceSettings.AutoFarm.Active, + (int)_tbotInstance.InstanceSettings.AutoFarm.MaxSlots, + (int)_tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Attack)), new RankSlotsPriority(Feature.Colonize, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.Colonize, - (bool) _tbotInstance.InstanceSettings.AutoColonize.Active, - (bool) _tbotInstance.InstanceSettings.AutoColonize.IntensiveResearch.Active ? - (int) _tbotInstance.InstanceSettings.AutoColonize.IntensiveResearch.MaxSlots : - 1, - (int) _tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Colonize)), + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.Colonize, + (bool)_tbotInstance.InstanceSettings.AutoColonize.Active, + (bool)_tbotInstance.InstanceSettings.AutoColonize.IntensiveResearch.Active ? + (int)_tbotInstance.InstanceSettings.AutoColonize.IntensiveResearch.MaxSlots : 1, + (int)_tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Colonize)), new RankSlotsPriority(Feature.AutoDiscovery, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoDiscovery, - (bool) _tbotInstance.InstanceSettings.AutoDiscovery.Active, - (int) _tbotInstance.InstanceSettings.AutoDiscovery.MaxSlots, - (int) _tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Discovery)), + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoDiscovery, + (bool)_tbotInstance.InstanceSettings.AutoDiscovery.Active, + (int)_tbotInstance.InstanceSettings.AutoDiscovery.MaxSlots, + (int)_tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Discovery)), new RankSlotsPriority(Feature.Harvest, - (int) _tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoHarvest, - (bool) _tbotInstance.InstanceSettings.AutoHarvest.Active, - (int) _tbotInstance.InstanceSettings.AutoHarvest.MaxSlots, - (int) _tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Harvest)) + (int)_tbotInstance.InstanceSettings.General.SlotPriorityLevel.AutoHarvest, + (bool)_tbotInstance.InstanceSettings.AutoHarvest.Active, + (int)_tbotInstance.InstanceSettings.AutoHarvest.MaxSlots, + (int)_tbotInstance.UserData.fleets.Count(f => f.Mission == Missions.Harvest)) }; - int MaxSlots = _calculationService.CalcSlotsPriority(Feature.Expeditions, rankSlotsPriority, _tbotInstance.UserData.slots, _tbotInstance.UserData.fleets, (int) _tbotInstance.InstanceSettings.General.SlotsToLeaveFree); + + int MaxSlots = _tbotInstance.UserData.slots.Total + - (int)_tbotInstance.InstanceSettings.General.SlotsToLeaveFree; + + if (MaxSlots < 0) + MaxSlots = 0; int expsToSend; - if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "WaitForAllExpeditions") && (bool) _tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) { + if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "WaitForAllExpeditions") + && (bool)_tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) { if (_tbotInstance.UserData.slots.ExpInUse == 0) expsToSend = _tbotInstance.UserData.slots.ExpTotal; else @@ -120,25 +137,40 @@ protected override async Task Execute() { } else { expsToSend = Math.Min(_tbotInstance.UserData.slots.ExpFree, _tbotInstance.UserData.slots.Free); } + DoLog(LogLevel.Debug, $"Expedition slot free: {expsToSend}"); - if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "WaitForMajorityOfExpeditions") && (bool) _tbotInstance.InstanceSettings.Expeditions.WaitForMajorityOfExpeditions) { - if ((double) expsToSend < Math.Round((double) _tbotInstance.UserData.slots.ExpTotal / 2D, 0, MidpointRounding.ToZero) + 1D) { + + if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "WaitForMajorityOfExpeditions") + && (bool)_tbotInstance.InstanceSettings.Expeditions.WaitForMajorityOfExpeditions) { + if ((double)expsToSend < Math.Round((double)_tbotInstance.UserData.slots.ExpTotal / 2D, 0, MidpointRounding.ToZero) + 1D) { DoLog(LogLevel.Debug, $"Majority of expedition already in flight, Skipping..."); expsToSend = 0; } } + expsToSend = expsToSend < MaxSlots ? expsToSend : MaxSlots; + + if (expsToSend <= 0) { + var idleInterval = RandomizeHelper.CalcRandomInterval(IntervalType.AboutFiveMinutes); + var nowIdle = await _tbotOgameBridge.GetDateTime(); + DoLog(LogLevel.Information, "Expeditions idle – no free expedition slots"); + DoLog(LogLevel.Information, $"Next expedition check at {nowIdle.AddMilliseconds(idleInterval)}"); + ChangeWorkerPeriod(idleInterval); + return; + } + if (expsToSend > 0) { if (_tbotInstance.UserData.slots.ExpFree > 0) { if (_tbotInstance.UserData.slots.Free > 0) { + List origins = new(); if (_tbotInstance.InstanceSettings.Expeditions.Origin.Length > 0) { try { foreach (var origin in _tbotInstance.InstanceSettings.Expeditions.Origin) { Coordinate customOriginCoords = new( - (int) origin.Galaxy, - (int) origin.System, - (int) origin.Position, + (int)origin.Galaxy, + (int)origin.System, + (int)origin.Position, Enum.Parse(origin.Type.ToString()) ); Celestial customOrigin = _tbotInstance.UserData.celestials @@ -157,7 +189,14 @@ protected override async Task Execute() { _tbotInstance.UserData.celestials = await _tbotOgameBridge.UpdatePlanets(UpdateTypes.LFBonuses); origins.Add(_tbotInstance.UserData.celestials .OrderBy(planet => planet.Coordinate.Type == Celestials.Moon) - .ThenByDescending(planet => _calculationService.CalcFleetCapacity(planet.Ships, _tbotInstance.UserData.serverData, _tbotInstance.UserData.researches.HyperspaceTechnology, null, _tbotInstance.UserData.userInfo.Class, _tbotInstance.UserData.serverData.ProbeCargo)) + .ThenByDescending(planet => + _calculationService.CalcFleetCapacity( + planet.Ships, + _tbotInstance.UserData.serverData, + _tbotInstance.UserData.researches.HyperspaceTechnology, + null, + _tbotInstance.UserData.userInfo.Class, + _tbotInstance.UserData.serverData.ProbeCargo)) .First() ); } @@ -166,26 +205,84 @@ protected override async Task Execute() { _tbotInstance.UserData.celestials = await _tbotOgameBridge.UpdatePlanets(UpdateTypes.LFBonuses); origins.Add(_tbotInstance.UserData.celestials .OrderBy(planet => planet.Coordinate.Type == Celestials.Moon) - .ThenByDescending(planet => _calculationService.CalcFleetCapacity(planet.Ships, _tbotInstance.UserData.serverData, _tbotInstance.UserData.researches.HyperspaceTechnology, null, _tbotInstance.UserData.userInfo.Class, _tbotInstance.UserData.serverData.ProbeCargo)) + .ThenByDescending(planet => + _calculationService.CalcFleetCapacity( + planet.Ships, + _tbotInstance.UserData.serverData, + _tbotInstance.UserData.researches.HyperspaceTechnology, + null, + _tbotInstance.UserData.userInfo.Class, + _tbotInstance.UserData.serverData.ProbeCargo)) .First() ); } - if ((bool) _tbotInstance.InstanceSettings.Expeditions.RandomizeOrder) { + + if ((bool)_tbotInstance.InstanceSettings.Expeditions.RandomizeOrder) { origins = origins.Shuffle().ToList(); } + LFBonuses lfBonuses = origins.First().LFBonuses; + + _tbotInstance.UserData.fleets = await _fleetScheduler.UpdateFleets(); + + var expFleets = _tbotInstance.UserData.fleets + .Where(f => f.Mission == Missions.Expedition && f.Origin != null) + .ToList(); + + DoLog(LogLevel.Warning, $"[EXP DEBUG] Active expeditions total = {expFleets.Count}"); + + foreach (var f in expFleets) { + DoLog( + LogLevel.Warning, + $"[EXP DEBUG] Fleet origin: G{f.Origin.Galaxy}:{f.Origin.System}:{f.Origin.Position} Type={f.Origin.Type}" + ); + } + int maxPerOrigin = int.MaxValue; + if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "MaxExpeditionsPerOrigin")) { + maxPerOrigin = (int)_tbotInstance.InstanceSettings.Expeditions.MaxExpeditionsPerOrigin; + } + + DoLog(LogLevel.Warning, + $"[EXP DEBUG] Origins count={origins.Count}, expsToSend={expsToSend}, maxPerOrigin={maxPerOrigin}"); + + var capacity = new Dictionary(); + foreach (var o in origins) { + int active = CountActiveExpeditionsFromOrigin(o); + int cap = Math.Max(0, maxPerOrigin - active); + capacity[o] = cap; + + DoLog(LogLevel.Warning, + $"[EXP DEBUG] Origin {o.Coordinate.Galaxy}:{o.Coordinate.System}:{o.Coordinate.Position} Type={o.Coordinate.Type} " + + $"active={active} maxPerOrigin={maxPerOrigin} cap={cap}"); + } + + var originExps = origins.ToDictionary(o => o, o => 0); + + int remaining = Math.Min(expsToSend, capacity.Values.Sum()); + + while (remaining > 0) { + bool progressed = false; + + foreach (var o in origins) { + if (remaining <= 0) break; + + if (originExps[o] < capacity[o]) { + originExps[o]++; + remaining--; + progressed = true; + } + } + + if (!progressed) break; + } + + foreach (var o in origins) { + DoLog(LogLevel.Warning, + $"[EXP DEBUG] PLAN origin {o.Coordinate.Galaxy}:{o.Coordinate.System}:{o.Coordinate.Position} Type={o.Coordinate.Type} " + + $"willSend={originExps[o]} (cap={capacity[o]})"); + } - LFBonuses lfBonuses = origins.First().LFBonuses; - Dictionary originExps = new(); - int quot = (int) Math.Floor((float) expsToSend / (float) origins.Count()); - foreach (var origin in origins) { - originExps.Add(origin, quot); - } - int rest = (int) Math.Floor((float) expsToSend % (float) origins.Count()); - for (int i = 0; i < rest; i++) { - originExps[origins[i]]++; - } int delayExpedition = 0; - foreach (var origin in originExps.Keys) { + foreach (var origin in origins) { int expsToSendFromThisOrigin = originExps[origin]; if (expsToSendFromThisOrigin == 0) { if (delayExpedition > 0) @@ -199,28 +296,28 @@ protected override async Task Execute() { continue; } else { Ships fleet; - if ((bool) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Active) { + if ((bool)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Active) { fleet = new( - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.LightFighter, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.HeavyFighter, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Cruiser, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Battleship, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Battlecruiser, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Bomber, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Destroyer, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Deathstar, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.SmallCargo, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.LargeCargo, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.ColonyShip, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Recycler, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.EspionageProbe, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.LightFighter, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.HeavyFighter, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Cruiser, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Battleship, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Battlecruiser, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Bomber, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Destroyer, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Deathstar, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.SmallCargo, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.LargeCargo, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.ColonyShip, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Recycler, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.EspionageProbe, 0, 0, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Reaper, - (long) _tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Pathfinder + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Reaper, + (long)_tbotInstance.InstanceSettings.Expeditions.ManualShips.Ships.Pathfinder ); if (!origin.Ships.HasAtLeast(fleet, expsToSendFromThisOrigin)) { - DoLog(LogLevel.Warning, $"Unable to send expeditions: not enough ships in origin {origin.ToString()}"); + DoLog(LogLevel.Warning, $"Unable to send expeditions: not enough ships in origin {origin}"); delayExpedition++; continue; } @@ -237,65 +334,34 @@ protected override async Task Execute() { } var availableShips = origin.Ships.GetMovableShips(); - if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "PrimaryToKeep") && (int) _tbotInstance.InstanceSettings.Expeditions.PrimaryToKeep > 0) { - availableShips.SetAmount(primaryShip, Math.Max(0, availableShips.GetAmount(primaryShip) - (long) _tbotInstance.InstanceSettings.Expeditions.PrimaryToKeep)); - } - DoLog(LogLevel.Warning, $"Available {primaryShip.ToString()} in origin {origin.ToString()}: {availableShips.GetAmount(primaryShip)} ({_tbotInstance.InstanceSettings.Expeditions.PrimaryToKeep} must be kept at dock)"); - fleet = _calculationService.CalcFullExpeditionShips(availableShips, primaryShip, expsToSendFromThisOrigin, _tbotInstance.UserData.serverData, _tbotInstance.UserData.researches, lfBonuses, _tbotInstance.UserData.userInfo.Class, _tbotInstance.UserData.serverData.ProbeCargo); - if (fleet.GetAmount(primaryShip) < (long) _tbotInstance.InstanceSettings.Expeditions.MinPrimaryToSend || availableShips.GetAmount(primaryShip) < 1) { - fleet.SetAmount(primaryShip, (long) _tbotInstance.InstanceSettings.Expeditions.MinPrimaryToSend); - if (availableShips.GetAmount(primaryShip) < 1) { - DoLog(LogLevel.Warning, $"Unable to send expeditions: no ships available in origin {origin.ToString()}"); - delayExpedition++; - continue; - } - if (!availableShips.HasAtLeast(fleet, expsToSendFromThisOrigin)) { - DoLog(LogLevel.Warning, $"Unable to send expeditions: available {primaryShip.ToString()} in origin {origin.ToString()} under set min number of {(long) _tbotInstance.InstanceSettings.Expeditions.MinPrimaryToSend}"); - delayExpedition++; - continue; - } - } - Buildables secondaryShip = Buildables.Null; - if (!Enum.TryParse(_tbotInstance.InstanceSettings.Expeditions.SecondaryShip, true, out secondaryShip)) { - DoLog(LogLevel.Warning, "Unable to parse SecondaryShip. Falling back to default Null"); - secondaryShip = Buildables.Null; - } - if (secondaryShip != Buildables.Null) { - long secondaryToSend = Math.Min( - (long) Math.Round( - availableShips.GetAmount(secondaryShip) / (float) expsToSendFromThisOrigin, - 0, - MidpointRounding.ToZero - ), - (long) Math.Round( - fleet.GetAmount(primaryShip) * (float) _tbotInstance.InstanceSettings.Expeditions.SecondaryToPrimaryRatio, - 0, - MidpointRounding.ToZero - ) - ); - if (secondaryToSend < (long) _tbotInstance.InstanceSettings.Expeditions.MinSecondaryToSend) { - DoLog(LogLevel.Warning, $"Unable to send expeditions: available {secondaryShip.ToString()} in origin {origin.ToString()} under set number of {(long) _tbotInstance.InstanceSettings.Expeditions.MinSecondaryToSend}"); - delayExpedition++; - continue; - } else { - fleet.Add(secondaryShip, secondaryToSend); - if (!availableShips.HasAtLeast(fleet, expsToSendFromThisOrigin)) { - DoLog(LogLevel.Warning, $"Unable to send expeditions: not enough ships in origin {origin.ToString()}"); - delayExpedition++; - continue; - } - } + if (SettingsService.IsSettingSet(_tbotInstance.InstanceSettings.Expeditions, "PrimaryToKeep") + && (int)_tbotInstance.InstanceSettings.Expeditions.PrimaryToKeep > 0) { + availableShips.SetAmount( + primaryShip, + Math.Max(0, availableShips.GetAmount(primaryShip) + - (long)_tbotInstance.InstanceSettings.Expeditions.PrimaryToKeep)); } + + fleet = _calculationService.CalcFullExpeditionShips( + availableShips, + primaryShip, + expsToSendFromThisOrigin, + _tbotInstance.UserData.serverData, + _tbotInstance.UserData.researches, + lfBonuses, + _tbotInstance.UserData.userInfo.Class, + _tbotInstance.UserData.serverData.ProbeCargo + ); } - DoLog(LogLevel.Information, $"{expsToSendFromThisOrigin.ToString()} expeditions with {fleet.ToString()} will be sent from {origin.ToString()}"); + DoLog(LogLevel.Information, $"{expsToSendFromThisOrigin} expeditions with {fleet} will be sent from {origin}"); + List syslist = new(); for (int i = 0; i < expsToSendFromThisOrigin; i++) { Coordinate destination; - if ((bool) _tbotInstance.InstanceSettings.Expeditions.SplitExpeditionsBetweenSystems.Active) { + if ((bool)_tbotInstance.InstanceSettings.Expeditions.SplitExpeditionsBetweenSystems.Active) { var rand = new Random(); - - int range = (int) _tbotInstance.InstanceSettings.Expeditions.SplitExpeditionsBetweenSystems.Range; + int range = (int)_tbotInstance.InstanceSettings.Expeditions.SplitExpeditionsBetweenSystems.Range; while (expsToSendFromThisOrigin > range * 2) range += 1; @@ -317,36 +383,58 @@ protected override async Task Execute() { Type = Celestials.DeepSpace }; } + _tbotInstance.UserData.slots = await _tbotOgameBridge.UpdateSlots(); - Resources payload = new(); - if ((long) _tbotInstance.InstanceSettings.Expeditions.FuelToCarry > 0) { - payload.Deuterium = (long) _tbotInstance.InstanceSettings.Expeditions.FuelToCarry; - } + Resources payload = new(); + if ((long)_tbotInstance.InstanceSettings.Expeditions.FuelToCarry > 0) { + payload.Deuterium = (long)_tbotInstance.InstanceSettings.Expeditions.FuelToCarry; + } if (_tbotInstance.UserData.slots.ExpFree > 0) { - var fleetId = await _fleetScheduler.SendFleet(origin, fleet, destination, Missions.Expedition, Speeds.HundredPercent, payload); - if (fleetId == (int) SendFleetCode.AfterSleepTime) { + var originUpdated = await _tbotOgameBridge.UpdatePlanet(origin, UpdateTypes.Ships); + + _tbotInstance.UserData.slots = await _tbotOgameBridge.UpdateSlots(); + if (_tbotInstance.UserData.slots.ExpFree <= 0) { + DoLog(LogLevel.Information, "Unable to send expeditions: no expedition slots available."); + delay = true; + return; + } + + if (fleet == null || fleet.IsEmpty() || !originUpdated.Ships.HasAtLeast(fleet, 1)) { + DoLog(LogLevel.Warning, $"Skipping expedition: no ships available on origin {originUpdated}"); + delayExpedition++; + break; + } + + var fleetId = await _fleetScheduler.SendFleet( + originUpdated, + fleet, + destination, + Missions.Expedition, + Speeds.HundredPercent, + payload + ); + if (fleetId == (int)SendFleetCode.AfterSleepTime) { stop = true; return; } - if (fleetId == (int) SendFleetCode.NotEnoughSlots) { + if (fleetId == (int)SendFleetCode.NotEnoughSlots) { delay = true; return; } - - var minWaitNextFleet = (int) _tbotInstance.InstanceSettings.Expeditions.MinWaitNextFleet; - var maxWaitNextFleet = (int) _tbotInstance.InstanceSettings.Expeditions.MaxWaitNextFleet; - if (minWaitNextFleet < 0) - minWaitNextFleet = 0; - if (maxWaitNextFleet < 1) - maxWaitNextFleet = 1; + int minWait = (int)_tbotInstance.InstanceSettings.Expeditions.MinWaitNextFleet; + int maxWait = (int)_tbotInstance.InstanceSettings.Expeditions.MaxWaitNextFleet; - var rndWaitTimeMs = (int) RandomizeHelper.CalcRandomIntervalSecToMs(minWaitNextFleet, maxWaitNextFleet); + if (maxWait < minWait) { + DoLog(LogLevel.Warning, + $"Expeditions wait misconfigured (MinWaitNextFleet={minWait} > MaxWaitNextFleet={maxWait}). Swapping values."); + (minWait, maxWait) = (maxWait, minWait); + } + var rndWaitTimeMs = (int)RandomizeHelper.CalcRandomIntervalSecToMs(minWait, maxWait); - DoLog(LogLevel.Information, $"Wait {((float) rndWaitTimeMs / 1000).ToString("0.00")}s for next Expedition"); + DoLog(LogLevel.Information, $"Wait {(rndWaitTimeMs / 1000f):0.00}s for next Expedition"); await Task.Delay(rndWaitTimeMs, _ct); - } else { DoLog(LogLevel.Information, "Unable to send expeditions: no expedition slots available."); delay = true; @@ -355,11 +443,7 @@ protected override async Task Execute() { } } } - } else { - DoLog(LogLevel.Warning, "Unable to send expeditions: no fleet slots available"); } - } else { - DoLog(LogLevel.Warning, "Unable to send expeditions: no expeditions slots available"); } } @@ -367,47 +451,42 @@ protected override async Task Execute() { List orderedFleets = _tbotInstance.UserData.fleets .Where(fleet => fleet.Mission == Missions.Expedition) .ToList(); - if ((bool) _tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) { - orderedFleets = orderedFleets - .OrderByDescending(fleet => fleet.BackIn) - .ToList(); + + if ((bool)_tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) { + orderedFleets = orderedFleets.OrderByDescending(fleet => fleet.BackIn).ToList(); } else { - orderedFleets = orderedFleets - .OrderBy(fleet => fleet.BackIn) - .ToList(); + orderedFleets = orderedFleets.OrderBy(fleet => fleet.BackIn).ToList(); } _tbotInstance.UserData.slots = await _tbotOgameBridge.UpdateSlots(); - if ((orderedFleets.Count() == 0) || (_tbotInstance.UserData.slots.ExpFree > 0 && (!((bool) _tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) && !((bool) _tbotInstance.InstanceSettings.Expeditions.WaitForMajorityOfExpeditions)))) { - interval = RandomizeHelper.CalcRandomInterval(IntervalType.AboutFiveMinutes); + if ((orderedFleets.Count == 0) || + (_tbotInstance.UserData.slots.ExpFree > 0 && + !((bool)_tbotInstance.InstanceSettings.Expeditions.WaitForAllExpeditions) && + !((bool)_tbotInstance.InstanceSettings.Expeditions.WaitForMajorityOfExpeditions))) { + interval = RandomizeHelper.CalcRandomInterval(IntervalType.AboutFiveMinutes); } else { - - var minWaitNextRound = (int) _tbotInstance.InstanceSettings.Expeditions.MinWaitNextRound; - var maxWaitNextRound = (int) _tbotInstance.InstanceSettings.Expeditions.MaxWaitNextRound; - - if (minWaitNextRound < 0) minWaitNextRound = 0; - if (maxWaitNextRound < 1) maxWaitNextRound = 1; - - interval = (int) ((1000 * orderedFleets.First().BackIn) + RandomizeHelper.CalcRandomIntervalSecToMs(minWaitNextRound, maxWaitNextRound)); - + interval = (int)((1000 * orderedFleets.First().BackIn) + + RandomizeHelper.CalcRandomIntervalSecToMs( + (int)_tbotInstance.InstanceSettings.Expeditions.MinWaitNextRound, + (int)_tbotInstance.InstanceSettings.Expeditions.MaxWaitNextRound)); } + time = await _tbotOgameBridge.GetDateTime(); - if (interval <= 0) - interval = RandomizeHelper.CalcRandomInterval(IntervalType.SomeSeconds); newTime = time.AddMilliseconds(interval); ChangeWorkerPeriod(interval); - DoLog(LogLevel.Information, $"Next check at {newTime.ToString()}"); + DoLog(LogLevel.Information, $"Next check at {newTime}"); await _tbotOgameBridge.CheckCelestials(); } - } catch (Exception e) { + } + catch (Exception e) { DoLog(LogLevel.Warning, $"HandleExpeditions exception: {e.Message}"); DoLog(LogLevel.Warning, $"Stacktrace: {e.StackTrace}"); - long interval = (long) (RandomizeHelper.CalcRandomInterval(IntervalType.AMinuteOrTwo)); + long interval = RandomizeHelper.CalcRandomInterval(IntervalType.AMinuteOrTwo); var time = await _tbotOgameBridge.GetDateTime(); - DateTime newTime = time.AddMilliseconds(interval); ChangeWorkerPeriod(interval); - DoLog(LogLevel.Information, $"Next check at {newTime.ToString()}"); - } finally { + DoLog(LogLevel.Information, $"Next check at {time.AddMilliseconds(interval)}"); + } + finally { if (!_tbotInstance.UserData.isSleeping) { if (stop) { DoLog(LogLevel.Information, $"Stopping feature."); @@ -419,13 +498,15 @@ protected override async Task Execute() { _tbotInstance.UserData.fleets = await _fleetScheduler.UpdateFleets(); long interval; try { - interval = (_tbotInstance.UserData.fleets.OrderBy(f => f.BackIn).First().BackIn ?? 0) * 1000 + RandomizeHelper.CalcRandomInterval(IntervalType.SomeSeconds); + interval = (_tbotInstance.UserData.fleets.OrderBy(f => f.BackIn).First().BackIn ?? 0) * 1000 + + RandomizeHelper.CalcRandomInterval(IntervalType.SomeSeconds); } catch { - interval = RandomizeHelper.CalcRandomInterval((int) _tbotInstance.InstanceSettings.Expeditions.CheckIntervalMin, (int) _tbotInstance.InstanceSettings.Expeditions.CheckIntervalMax); + interval = RandomizeHelper.CalcRandomInterval( + (int)_tbotInstance.InstanceSettings.Expeditions.CheckIntervalMin, + (int)_tbotInstance.InstanceSettings.Expeditions.CheckIntervalMax); } - var newTime = time.AddMilliseconds(interval); ChangeWorkerPeriod(interval); - DoLog(LogLevel.Information, $"Next check at {newTime.ToString()}"); + DoLog(LogLevel.Information, $"Next check at {time.AddMilliseconds(interval)}"); } await _tbotOgameBridge.CheckCelestials(); }