示例#1
0
 protected virtual void TriggerRelease(Event @event = null)
 {
     while (ReleaseQueue.Count > 0)
     {
         var release = ReleaseQueue.Peek();
         if (release.Request.IsAlive)
         {
             if (!RequestQueue.Remove(release.Request))
             {
                 throw new InvalidOperationException("Failed to cancel a request.");
             }
             BreakOffTime?.Add(Environment.ToDouble(Environment.Now - release.Request.Time));
             release.Succeed();
             ReleaseQueue.Dequeue();
         }
         else
         {
             DoRelease(release);
             if (release.IsTriggered)
             {
                 ReleaseQueue.Dequeue();
                 TriggerWhenAny();
                 TriggerWhenFull();
                 TriggerWhenChange();
             }
             else
             {
                 break;
             }
         }
     }
     Utilization?.UpdateTo(InUse / (double)Capacity);
     WIP?.UpdateTo(InUse + RequestQueue.Count);
     QueueLength?.UpdateTo(RequestQueue.Count);
 }
示例#2
0
        protected virtual void TriggerGet(Event @event = null)
        {
            var current = GetQueue.First;

            while (current != null)
            {
                var get = current.Value;
                DoGet(get);
                if (get.IsTriggered)
                {
                    var next = current.Next;
                    GetQueue.Remove(current);
                    current = next;
                    TriggerWhenEmpty();
                    TriggerWhenChange();
                }
                else
                {
                    current = current.Next;
                }
                if (Items.Count == 0)
                {
                    break;
                }
            }
            Utilization?.UpdateTo(Count / (double)Capacity);
            WIP?.UpdateTo(Count + PutQueue.Count + GetQueue.Count);
            GetQueueLength?.UpdateTo(GetQueue.Count);
        }
示例#3
0
        protected virtual void TriggerRequest(Event @event = null)
        {
            var current = RequestQueue.First;

            while (current != null)
            {
                var request = current.Value;
                DoRequest(request);
                if (request.IsTriggered)
                {
                    var next = current.Next;
                    RequestQueue.Remove(current);
                    current = next;
                    TriggerWhenEmpty();
                    TriggerWhenChange();
                }
                else
                {
                    current = current.Next;
                }
                if (Resources.Count == 0)
                {
                    break;
                }
            }
            Utilization?.UpdateTo(InUse / (double)Capacity);
            WIP?.UpdateTo(InUse + RequestQueue.Count);
            QueueLength?.UpdateTo(RequestQueue.Count);
        }
示例#4
0
        private IEnumerable <Event> Main()
        {
            while (true)
            {
                Priority = _pendingPrio;
                Mode     = _pendingMode;
                switch (Mode)
                {
                case CraneAgentMode.Idle:
                    State = CraneAgentState.Waiting;
                    Utilization?.UpdateTo(0);
                    _interruptible = true;
                    yield return(new Event(_world.Environment));

                    _world.Environment.ActiveProcess.HandleFault();
                    continue;

                case CraneAgentMode.Dodge:
                    State = CraneAgentState.Moving;
                    Utilization?.UpdateTo(1);
                    _interruptible = true;
                    var moveProcess = _world.Environment.Process(MoveCrane(_dodgePosition, _dodgePosition));
                    yield return(moveProcess);

                    if (_world.Environment.ActiveProcess.HandleFault())
                    {
                        moveProcess.Interrupt();
                        _interruptible = false;
                        yield return(moveProcess);

                        continue;
                    }
                    _pendingMode = CraneAgentMode.Work;
                    _pendingPrio = null;
                    break;

                case CraneAgentMode.Work:
                    var workingProcess = _world.Environment.Process(Working());
                    _interruptible = true;
                    yield return(workingProcess);

                    if (_world.Environment.ActiveProcess.HandleFault())
                    {
                        workingProcess.Interrupt();
                        _interruptible = false;
                        yield return(workingProcess);

                        continue;
                    }
                    break;

                default: throw new InvalidOperationException($"Error in CraneAgent, unknown mode: {_pendingMode}.");
                }
            }
        }
示例#5
0
 protected virtual void TriggerGet(Event @event = null)
 {
     while (GetQueue.Count > 0)
     {
         var get = GetQueue.Peek();
         DoGet(get);
         if (get.IsTriggered)
         {
             GetQueue.Dequeue();
             TriggerWhenEmpty();
             TriggerWhenChange();
         }
         else
         {
             break;
         }
     }
     Utilization?.UpdateTo(Count / (double)Capacity);
     WIP?.UpdateTo(Count + PutQueue.Count + GetQueue.Count);
     GetQueueLength?.UpdateTo(GetQueue.Count);
 }
示例#6
0
 protected virtual void TriggerRequest(Event @event = null)
 {
     while (RequestQueue.Count > 0)
     {
         var request = RequestQueue.First.Value;
         DoRequest(request);
         if (request.IsTriggered)
         {
             RequestQueue.RemoveFirst();
             TriggerWhenEmpty();
             TriggerWhenChange();
         }
         else
         {
             break;
         }
     }
     Utilization?.UpdateTo(InUse / (double)Capacity);
     WIP?.UpdateTo(InUse + RequestQueue.Count);
     QueueLength?.UpdateTo(RequestQueue.Count);
 }
示例#7
0
 protected virtual void TriggerPickup(Event @event = null)
 {
     while (PickupQueue.Count > 0)
     {
         var get = PickupQueue.First.Value;
         DoPickup(get);
         if (get.IsTriggered)
         {
             PickupQueue.RemoveFirst();
             TriggerWhenEmpty();
             TriggerWhenChange();
         }
         else
         {
             break;
         }
     }
     Utilization?.UpdateTo(Location.Height / (double)Location.MaxHeight);
     WIP?.UpdateTo(Location.Height + DropoffQueue.Count + PickupQueue.Count);
     PickupQueueLength?.UpdateTo(PickupQueue.Count);
 }
示例#8
0
 protected virtual void TriggerPut(Event @event = null)
 {
     while (PutQueue.Count > 0)
     {
         var put = PutQueue.Peek();
         DoPut(put);
         if (put.IsTriggered)
         {
             PutQueue.Dequeue();
             TriggerWhenNew();
             TriggerWhenAny();
             TriggerWhenFull();
             TriggerWhenChange();
         }
         else
         {
             break;
         }
     }
     Utilization?.UpdateTo(Count / (double)Capacity);
     WIP?.UpdateTo(Count + PutQueue.Count + GetQueue.Count);
     PutQueueLength?.UpdateTo(PutQueue.Count);
 }
示例#9
0
 protected virtual void TriggerDropoff(Event @event = null)
 {
     while (DropoffQueue.Count > 0)
     {
         var put = DropoffQueue.First.Value;
         DoDropoff(put);
         if (put.IsTriggered)
         {
             DropoffQueue.RemoveFirst();
             TriggerWhenNew();
             TriggerWhenAny();
             TriggerWhenFull();
             TriggerWhenChange();
         }
         else
         {
             break;
         }
     }
     Utilization?.UpdateTo(Location.Height / (double)Location.MaxHeight);
     WIP?.UpdateTo(Location.Height + DropoffQueue.Count + PickupQueue.Count);
     DropoffQueueLength?.UpdateTo(DropoffQueue.Count);
 }
示例#10
0
        private IEnumerable <Event> MoveCrane(double targetPosition, double goalPos2)
        {
            UpdatePosition();
            GoalPosition1 = targetPosition;
            GoalPosition2 = goalPos2;

            var speed = GirderSpeed.GetValue();

            while (Math.Abs(targetPosition - _crane.GirderPosition) > 0.01)
            {
                var collider = targetPosition != _crane.GirderPosition ? GetPotentialCollider() : null;
                _targetGirderPosition = _crane.GirderPosition;

                if (collider == null)
                {
                    _targetGirderPosition = _world.ZoneControl.GetClosestToTarget(this, targetPosition);

                    // CASE 1: No collision expected, move to target
                    var sftDist = _crane.Width / 2;
                    if (_crane.GirderPosition < _targetGirderPosition)
                    {
                        sftDist = -sftDist;
                    }
                    var stackHeight = _world.HeightBetween(_crane.GirderPosition + sftDist, targetPosition - sftDist);
                    if (_crane.HoistLevel < stackHeight + 1)
                    {
                        yield return(_world.Environment.Process(MoveHoist(stackHeight + 1)));
                    }

                    _girderSpeed = _targetGirderPosition < _crane.GirderPosition ? -speed : speed;
                    var timeout = _world.Environment.Timeout(TimeSpan.FromSeconds(Math.Abs(_targetGirderPosition - _crane.GirderPosition) / Math.Abs(_girderSpeed)));
                    timeout.AddCallback(_ => { UpdatePosition(); _girderSpeed = 0; _crane.GirderPosition = _targetGirderPosition; });
                    yield return(timeout & _world.ReactionTime());

                    _world.ZoneControl.MoveUpdate();
                }
                else
                {
                    // CASE 2: Avoid potential collision
                    if (collider.State == CraneAgentState.Waiting)
                    {
                        // CASE 2a: collider is idleing, tell it to dodge
                        var dodgePoint = targetPosition < _crane.GirderPosition ? Math.Min(targetPosition, GoalPosition2) - Width / 2 - collider.Width / 2
                                                                   : Math.Max(targetPosition, GoalPosition2) + Width / 2 + collider.Width / 2;
                        if (collider.Mode == CraneAgentMode.Idle)
                        {
                            Utilization?.UpdateTo(0);
                            yield return(_world.ReactionTime());

                            Utilization?.UpdateTo(1);
                        }
                        else
                        {
                            collider.Dodge(dodgePoint, Priority);
                            _targetGirderPosition = _world.ZoneControl.GetClosestToTarget(this, targetPosition < _crane.GirderPosition
                ? collider.GetGirderPosition() + collider.Width / 2 + Width / 2
                : collider.GetGirderPosition() - collider.Width / 2 - Width / 2);

                            var sftDist = _crane.Width / 2;
                            if (_crane.GirderPosition < _targetGirderPosition)
                            {
                                sftDist = -sftDist;
                            }
                            var stackHeight = _world.HeightBetween(_crane.GirderPosition + sftDist, targetPosition - sftDist);
                            if (_crane.HoistLevel < stackHeight + 1)
                            {
                                yield return(_world.Environment.Process(MoveHoist(stackHeight + 1)));
                            }

                            _girderSpeed = _targetGirderPosition < _crane.GirderPosition ? -speed : speed;
                            var timeout = _world.Environment.Timeout(TimeSpan.FromSeconds(Math.Abs(_targetGirderPosition - _crane.GirderPosition) / Math.Abs(_girderSpeed)));
                            timeout.AddCallback(_ => { UpdatePosition(); _girderSpeed = 0; _crane.GirderPosition = _targetGirderPosition; });
                            yield return(timeout & _world.ReactionTime());

                            _world.ZoneControl.MoveUpdate();
                        }
                    }
                    else
                    {
                        // Case 2b: The collider is moving or servicing
                        // Calculate the point at which a collision would occur, either the other's current position or its target position
                        var collisionPoint = targetPosition < _crane.GirderPosition ? Math.Max(collider.GetGirderPosition(), collider.TargetPosition) + collider.Width / 2 + Width / 2
                                                                        : Math.Min(collider.GetGirderPosition(), collider.TargetPosition) - collider.Width / 2 - Width / 2;

                        var dodgePoint = targetPosition < _crane.GirderPosition ? Math.Max(Math.Max(Math.Max(collider.GetGirderPosition(), collider.GoalPosition1), collider.GoalPosition2), collider.TargetPosition) + collider.Width / 2 + Width / 2
                                                                    : Math.Min(Math.Min(Math.Min(collider.GetGirderPosition(), collider.GoalPosition1), collider.GoalPosition2), collider.TargetPosition) - collider.Width / 2 - Width / 2;
                        if (Priority > collider.Priority)
                        {
                            var tgt = _crane.GirderPosition < collider.GetGirderPosition() ? Math.Min(dodgePoint, targetPosition) - 1e-7: Math.Max(dodgePoint, targetPosition) + 1e-7;
                            if (Math.Abs(tgt - _crane.GirderPosition) > 1e-5)
                            {
                                var oldPrio = Priority;
                                // to propagate priority onto dodgers e.g. 4 -> 4.5 -> 4.75 -> 4.875
                                // this is necessary so that a dodger is able to cause further cranes to dodge
                                Priority = (collider.Priority + Math.Ceiling((collider.Priority ?? 0) + 1e-7)) / 2.0;
                                if (Math.Abs(_crane.GirderPosition - tgt) < 1e-5)
                                {
                                    Utilization?.UpdateTo(0);
                                    yield return(_world.ReactionTime());

                                    Utilization?.UpdateTo(1);
                                }
                                else
                                {
                                    yield return(_world.AtLeastReactionTime(MoveCrane(tgt, tgt)));
                                }
                                GoalPosition1 = targetPosition;
                                GoalPosition2 = goalPos2;
                                Priority      = oldPrio;
                            }
                            else
                            {
                                Utilization?.UpdateTo(0);
                                yield return(_world.ReactionTime());

                                Utilization?.UpdateTo(1);
                            }
                        }
                        else
                        {
                            _targetGirderPosition = _world.ZoneControl.GetClosestToTarget(this, _crane.GirderPosition < collider.GetGirderPosition()
                ? Math.Min(targetPosition, collisionPoint)
                : Math.Max(targetPosition, collisionPoint));

                            var sftDist = _crane.Width / 2;
                            if (_crane.GirderPosition < _targetGirderPosition)
                            {
                                sftDist = -sftDist;
                            }
                            var stackHeight = _world.HeightBetween(_crane.GirderPosition + sftDist, targetPosition - sftDist);
                            if (_crane.HoistLevel < stackHeight + 1)
                            {
                                yield return(_world.Environment.Process(MoveHoist(stackHeight + 1)));
                            }

                            _girderSpeed = _targetGirderPosition < _crane.GirderPosition ? -speed : speed;
                            var timeout = _world.Environment.Timeout(TimeSpan.FromSeconds(Math.Abs(_targetGirderPosition - _crane.GirderPosition) / Math.Abs(_girderSpeed)));
                            timeout.AddCallback(_ => { UpdatePosition(); _girderSpeed = 0; _crane.GirderPosition = _targetGirderPosition; });
                            yield return(timeout & _world.ReactionTime());

                            _world.ZoneControl.MoveUpdate();
                        }
                    }
                }

                UpdatePosition();
            }

            StopCrane();
        }
示例#11
0
        private IEnumerable <Event> Working()
        {
            State = CraneAgentState.Waiting;
            Utilization?.UpdateTo(0);
            Priority = null;
            var next = _world.CraneScheduleStore.Get(this);

            _interruptible = true;
            yield return(next);

            if (_world.Environment.ActiveProcess.HandleFault())
            {
                _world.CraneScheduleStore.CancelWaiting(next);
                yield break;
            }

            var move = next.Move;

            if (move.Amount < 0)
            {
                _world.Environment.Log($"Crane {Id}: Moving {move.Amount} number of blocks is not possible -> ignore.");
                yield break;
            }
            if (move.Type == MoveType.PickupAndDropoff && move.Amount > _crane.Capacity)
            {
                _world.Environment.Log($"Cannot {move.Type} {move.Amount} block(s). Crane carries {_crane.Load.Size} of {_crane.Capacity} blocks.");
                yield break;
            }
            if (move.Type == MoveType.PickupAndDropoff && move.Amount == 0 && _crane.Load.Size == 0)
            {
                _world.Environment.Log($"Crane {Id} should dropoff its current load at {move.PickupLocation}, but does not carry any blocks -> ignore.");
                yield break;
            }

            if (move.ReleaseTime > _world.Now)
            {
                // TODO: Throw, ignore, log, wait, ... !?
                yield return(_world.Environment.Timeout(move.ReleaseTime - _world.Now));

                if (_world.Environment.ActiveProcess.HandleFault())
                {
                    yield break;
                }
            }

            Priority = move.Id;
            State    = CraneAgentState.Moving;
            Utilization?.UpdateTo(1);

            GoalPosition1 = move.PickupGirderPosition;
            if (move.Amount > 0)
            {
                GoalPosition2 = move.DropoffGirderPosition;
            }
            else
            {
                GoalPosition2 = GoalPosition1;
            }

            Process doMove;

            yield return(doMove = _world.Environment.Process(MoveCrane(move.PickupGirderPosition, move.DropoffGirderPosition)));

            if (_world.Environment.ActiveProcess.HandleFault())
            {
                doMove.Interrupt();
                yield break;
            }

            if (move.Type == MoveType.MoveToPickup)
            {
                move.Finished.Succeed();
                yield break;
            }

            var pickupLoc = _world.LocationResources.Single(x => x.Id == move.PickupLocation);

            if (pickupLoc.Height + _crane.Load.Size < move.Amount) // any load will first be dropped when picking up blocks
            {
                _world.Environment.Log($"Cannot pickup {move.Amount} blocks from {move.PickupLocation}, only {pickupLoc.Height} blocks there.");
                move.Finished.Fail();
                yield break;
            }
            State          = CraneAgentState.Picking;
            _interruptible = false;
            yield return(_world.Environment.Process(MoveHoist(pickupLoc.Height)));

            yield return(_world.Environment.Process(DoPickupDropoff(pickupLoc, move.Amount)));

            yield return(_world.Environment.Process(MoveHoist(_world.Height - _crane.Capacity)));

            if (move.Amount > 0)
            {
                State = CraneAgentState.Moving;
                yield return(doMove = _world.Environment.Process(MoveCrane(move.DropoffGirderPosition, move.DropoffGirderPosition)));

                var dropoffLoc = _world.LocationResources.Single(x => x.Id == move.DropoffLocation);
                if (dropoffLoc.FreeHeight < move.Amount)
                {
                    _world.Environment.Log($"Cannot drop off {move.Amount} blocks at {move.DropoffLocation}, only {dropoffLoc.FreeHeight} free space.");
                    move.Finished.Fail();
                    _interruptible = true;
                    yield break;
                }
                State = CraneAgentState.Dropping;
                yield return(_world.Environment.Process(MoveHoist(dropoffLoc.Height)));

                yield return(_world.Environment.Process(DoPickupDropoff(dropoffLoc, 0)));
            }

            move.Finished.Succeed();

            if (move.RaiseHoistAfterService)
            {
                yield return(_world.Environment.Process(MoveHoist(_world.Height - _crane.Capacity)));
            }

            _interruptible = true;
        }