計算機科学のブログ

inheritance - Your object's family tree - Beehive Management System

Head First C#: A Learner’s Guide to Real-World Programming with C# and .NET Core (Andrew Stellman(著)、Jennifer Greene(著)、O’Reilly Media)のChapter 6(inheritance - Your object’s family tree)、p.320(Long Exercise)の解答を求めてみる。

コード

Bee.cs

using System;
namespace BeehiveManagementSystem
{
    public class Bee
    {
        public string Job { get; private set; }
        public virtual float CostPerShift { get; }

        public Bee(string job)
        {
            Job = job;
        }
        public void WorkTheNextShift()
        {
            if (HoneyValut.ConsumeHoney(CostPerShift))
            {
                DoJob();
            }
        }
        protected virtual void DoJob() { }
    }
}

コード

EggCare.cs

using System;
namespace BeehiveManagementSystem
{
    public class EggCare : Bee
    {
        private const float CARE_PROGRESS_PER_SHIFT = 0.15f;
        private Queen queen;
        public override float CostPerShift
        {
            get
            {
                return 1.35f;
            }
        }
        public EggCare(Queen queen) : base("Egg Care")
        {
            this.queen = queen;
        }
        protected override void DoJob()
        {
            queen.CareForEggs(CARE_PROGRESS_PER_SHIFT);
        }
    }
}

コード

HoneyManufacturer.cs

using System;
namespace BeehiveManagementSystem
{
    public class HoneyManufacturer : Bee
    {
        private const float NECTAR_PROCESSED_PER_SHIFT = 33.15f;
        public override float CostPerShift
        {
            get
            {
                return 1.7f;
            }
        }
        public HoneyManufacturer() : base("Honey Manufacturer")
        {
        }
        protected override void DoJob()
        {
            HoneyValut.ConvertNectarToHoney(NECTAR_PROCESSED_PER_SHIFT);
        }
    }
}

コード

HoneyVault.cs

using System;
namespace BeehiveManagementSystem
{
    public static class HoneyValut
    {
        private const float NECTAR_CONVERSION_RATIO = 0.19f;
        private const float LOW_LEVEL_WARNING = 10f;
        private static float honey = 25f;
        private static float nectar = 100f;
        public static string StatusReport
        {
            get
            {
                string s = $"amount of honey: {honey:0.0}\n" +
                    $"amount of nectar: {nectar:0.0}";
                if (honey <= LOW_LEVEL_WARNING)
                {
                    s += $"\nWarning: LOW HONEY - ADD A HONEY MANUFACTURER";
                }
                if (nectar <= LOW_LEVEL_WARNING)
                {
                    s += $"\nWarning: LOW NECTAR - ADD A NECTAR COLLECTOR";
                }
                return s;
            }
        }
        public static void CollectNectar(float amount)
        {
            if (amount > 0)
            {
                nectar += amount;
            }
        }
        public static void ConvertNectarToHoney(float amount)
        {
            if (nectar < amount)
            {
                amount = nectar;
            }
            nectar -= amount;
            honey += amount * NECTAR_CONVERSION_RATIO;

        }
        public static bool ConsumeHoney(float amount)
        {
            if (amount <= honey)
            {
                honey -= amount;
                return true;
            }
            return false;
        }
    }
}

コード

NectarCollector.cs

using System;
namespace BeehiveManagementSystem
{
    public class NectarCollector : Bee
    {
        private const float NECTAR_COLLECTED_PER_SHIFT = 33.25f;
        public override float CostPerShift
        {
            get
            {
                return 1.95f;
            }
        }
        public NectarCollector() : base("Nectar Collector")
        {
        }
        protected override void DoJob()
        {
            HoneyValut.CollectNectar(NECTAR_COLLECTED_PER_SHIFT);
        }
    }
}

コード

Queen.cs

using System;
namespace BeehiveManagementSystem
{
    public class Queen : Bee
    {
        private const float EGGS_PER_SHIFT = 0.45f;
        private const float HONEY_PER_UNASSIGNED_WORKER = 0.5f;
        private Bee[] workers = Array.Empty<Bee>();
        private float eggs = 0;
        private float unassignedWorkers = 3;

        public override float CostPerShift
        {
            get
            {
                return 2.15f;
            }
        }
        public string StatusReport { get; private set; }
        public Queen() : base("Queen")
        {
            AssignBee("Egg Care");
            AssignBee("Honey Manufacturer");
            AssignBee("Nectar Collector");
        }
        protected override void DoJob()
        {
            eggs += EGGS_PER_SHIFT;
            foreach (Bee worker in workers)
            {
                worker.WorkTheNextShift();
            }
            HoneyValut.ConsumeHoney(HONEY_PER_UNASSIGNED_WORKER * workers.Length);
            updateStatusReport();
        }
        public void AddWorker(Bee worker)
        {
            if (unassignedWorkers > 0)
            {
                unassignedWorkers--;
                Array.Resize(ref workers, workers.Length + 1);
                workers[workers.Length - 1] = worker;
            }
        }
        public void AssignBee(string job)
        {
            switch (job)
            {
                case "Egg Care":
                    AddWorker(new EggCare(this));
                    break;
                case "Honey Manufacturer":
                    AddWorker(new HoneyManufacturer());
                    break;
                case "Nectar Collector":
                    AddWorker(new NectarCollector());
                    break;
                default:
                    break;
            }
            updateStatusReport();
        }
        public void CareForEggs(float eggsToConvert)
        {
            if (eggs >= eggsToConvert)
            {
                eggs -= eggsToConvert;
                unassignedWorkers += eggsToConvert;
            }
        }
        private void updateStatusReport()
        {
            int nectarCollectorBeeCount = 0;
            int honeyManufacturerBeeCount = 0;
            int eggCareBeeCount = 0;
            foreach (Bee worker in workers)
            {
                switch (worker.Job)
                {
                    case "Nectar Collector":
                        nectarCollectorBeeCount++;
                        break;
                    case "Honey Manufacturer":
                        honeyManufacturerBeeCount++;
                        break;
                    case "Egg Care":
                        eggCareBeeCount++;
                        break;
                    default:
                        break;
                }
            }
            string nectors = "bee";
            string honeys = "bee";
            string eggCares = "bee";
            if (nectarCollectorBeeCount > 1)
            {
                nectors += "s";
            }
            if (honeyManufacturerBeeCount > 1)
            {
                honeys += "s";
            }
            if (eggCareBeeCount > 1)
            {
                eggCares += "s";
            }
            StatusReport = $"Vault report:\n{HoneyValut.StatusReport}\n\n" +
                $"Egg count: {eggs:0.0}\n" +
                $"Unassigned workers: {unassignedWorkers:0.0}\n" +
                $"{nectarCollectorBeeCount} NectarCollector {nectors}\n" +
                $"{honeyManufacturerBeeCount} Honey Manufacturer {honeys}\n" +
                $"{eggCareBeeCount} Egg Care {eggCares}\n" +
                $"TOTAL WORKERS: {workers.Length}";
        }
    }
}

Beehive Management System