Example #1
0
        /// <summary>
        /// Here we have a mock program that might be used as part of a simulation that is
        /// used to generate data to help choose the optimal location for a new grocery store
        /// co-op in a neighborhood of people who travel by foot and bicycle.
        /// The flyweight pattern is used to save RAM when creating the very large number
        /// of objects used to represent individual NeighborhoodMembers by separating out
        /// intrinsic state from extrinsic state and sharing state where it makes sense.
        /// </summary>
        /// <param name="args"></param>
        private static void Main(string[] args)
        {
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            Console.WriteLine("🚴 Starting City Planning Simulation for new Grocery Store Location");
            Console.WriteLine("--------------------------------------------------------------------");

            var       rng = new Random();
            const int simulationPopulationSize = 100_000;
            const int simulationHeightWidth    = 100;
            const int flyweightBankSize        = 5;

            var transportModes = new[] {
                new TransportationMethod("walk", 1),
                new TransportationMethod("bicycle", 2)
            };

            var subdivisions = new[] {
                new Subdivision("north_side", 120),
                new Subdivision("east_side", 210),
                new Subdivision("downtown", 300),
                new Subdivision("lakeside", 310)
            };

            var neighborhoodMembers = new NeighborhoodMember[flyweightBankSize];

            for (var i = 0; i < flyweightBankSize; i++)
            {
                var member = new NeighborhoodMember();
                var(x, y) = GetRandomCoordinates(rng, simulationHeightWidth);
                var modeOfTransport = GetRandomTransportation(rng, transportModes);
                var subdivision     = GetRandomSubdivision(rng, subdivisions);
                member.PositionX            = x;
                member.PositionY            = y;
                member.TransportationMethod = modeOfTransport;
                member.Subdivision          = subdivision;
                neighborhoodMembers[i]      = member;
            }

            var factory = new SharedStateFactory(neighborhoodMembers);

            factory.DisplayCache();

            for (var i = 0; i < simulationPopulationSize; i++)
            {
                var member = new NeighborhoodMember();
                var(item1, item2) = GetRandomCoordinates(rng, simulationHeightWidth);
                var modeOfTransport = GetRandomTransportation(rng, transportModes);
                var subdivision     = GetRandomSubdivision(rng, subdivisions);
                member.PositionX            = item1;
                member.PositionY            = item2;
                member.TransportationMethod = modeOfTransport;
                member.Subdivision          = subdivision;
                AddMemberToSimulation(factory, member, i);
            }

            Console.WriteLine("Simulation Complete.");
            Console.WriteLine("--------------------------------------------------------------------");
        }
Example #2
0
        private static void AddMemberToSimulation(
            SharedStateFactory factory,
            NeighborhoodMember member,
            int i)
        {
            var flyweight = factory.GetFlyweight(new NeighborhoodMember {
                TransportationMethod = member.TransportationMethod,
                Subdivision          = member.Subdivision
            });

            // Here, our simulation client calculates extrinsic state and passes
            // it to the flyweight's methods
            if (i % 10_000 != 0)
            {
                return;
            }
            Console.WriteLine($"Iteration # {i}");
            flyweight.RenderPosition(member);
        }