예제 #1
0
        /// <summary>
        /// Puts the given job into the end of the production line.
        /// </summary>
        /// <param name="productName">The name of the product to enqueue.</param>
        /// <param name="jobID">The ID of the job to enqueue.</param>
        /// <returns>True if enqueing the job was successful; otherwise false.</returns>
        public bool EnqueueJob(string productName, int jobID)
        {
            if (productName == null)
            {
                throw new ArgumentNullException("productName");
            }
            if (jobID < 0)
            {
                throw new ArgumentOutOfRangeException("jobID", "Production job ID must be non-negative!");
            }
            if (!this.products.ContainsKey(productName))
            {
                throw new InvalidOperationException(string.Format("Product '{0}' cannot be produced at this production line!", productName));
            }
            if (this.itemCount.Read() == this.Capacity)
            {
                throw new InvalidOperationException("This production line has reached its capacity!");
            }

            if (!this.CheckOwnerPlayer())
            {
                this.RemoveAllJobs();
                return(false);
            }

            /// Create a job and try to lock the resources of the owner player.
            ProductionJob job = this.CreateJob(productName, jobID);

            if (!job.LockResources())
            {
                /// Unable to lock the necessary resources -> abort the job and cancel.
                job.Dispose();
                return(false);
            }

            /// If there is no other job in the line, try to start the created job.
            if (this.itemCount.Read() == 0)
            {
                if (!job.Start())
                {
                    /// Unable to start the job -> abort the job and cancel.
                    job.Dispose();
                    return(false);
                }
            }

            /// Job created -> enqueue it.
            this.jobs[this.CalculatePhysicalIndex(this.itemCount.Read())].Write(job);
            this.itemCount.Write(this.itemCount.Read() + 1);
            return(true);
        }
예제 #2
0
        /// <summary>
        /// Removes the given job from the production line.
        /// </summary>
        /// <param name="jobID">The ID of the job to remove.</param>
        /// <remarks>If there is no job with the given ID then this function has no effect.</remarks>
        public void RemoveJob(int jobID)
        {
            if (jobID < 0)
            {
                throw new ArgumentOutOfRangeException("jobID", "Production job ID must be non-negative!");
            }

            if (!this.CheckOwnerPlayer())
            {
                this.RemoveAllJobs();
                return;
            }

            int indexOfRemovedJob = -1;

            for (int index = 0; index < this.itemCount.Read(); index++)
            {
                int physicalIndex = this.CalculatePhysicalIndex(index);
                if (indexOfRemovedJob == -1 && this.jobs[physicalIndex].Read().ID == jobID)
                {
                    /// Job found -> abort and remove it from the line.
                    this.jobs[physicalIndex].Read().Dispose();
                    this.jobs[physicalIndex].Write(null);
                    indexOfRemovedJob = index;
                }

                /// Replace the current item with the next item if the job has already been removed.
                if (indexOfRemovedJob != -1 && index < this.itemCount.Read() - 1)
                {
                    int physicalIndexOfNext = this.CalculatePhysicalIndex(index + 1);
                    this.jobs[physicalIndex].Write(this.jobs[physicalIndexOfNext].Read());
                    this.jobs[physicalIndexOfNext].Write(null);
                }
            }

            /// If the job has been removed, decrement the itemCount.
            if (indexOfRemovedJob != -1)
            {
                this.itemCount.Write(this.itemCount.Read() - 1);
            }

            /// If the first job has been removed, try to start the next job.
            if (indexOfRemovedJob == 0 && this.itemCount.Read() > 0)
            {
                ProductionJob nextJob = this.jobs[this.CalculatePhysicalIndex(0)].Read();
                nextJob.Start();
            }
        }
예제 #3
0
        /// <summary>
        /// Continues the current production job.
        /// </summary>
        public void ContinueProduction()
        {
            if (this.itemCount.Read() == 0)
            {
                throw new InvalidOperationException("This production line is inactive!");
            }

            if (!this.CheckOwnerPlayer())
            {
                this.RemoveAllJobs();
                return;
            }

            ProductionJob currentJob = this.jobs[this.CalculatePhysicalIndex(0)].Read();

            if (currentJob.IsStarted)
            {
                /// Current job has been started -> continue it.
                if (currentJob.Continue())
                {
                    /// Current job finished working -> remove it from the line.
                    currentJob.Dispose();
                    this.jobs[this.CalculatePhysicalIndex(0)].Write(null);
                    this.startIndex.Write((this.startIndex.Read() + 1) % this.Capacity);
                    this.itemCount.Write(this.itemCount.Read() - 1);

                    /// If we still have jobs in the line, try to start the next one.
                    if (this.itemCount.Read() > 0)
                    {
                        ProductionJob nextJob = this.jobs[this.CalculatePhysicalIndex(0)].Read();
                        nextJob.Start();
                    }
                }
            }
            else
            {
                /// Try to start the current job.
                currentJob.Start();
            }
        }