summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-11-20 19:17:14 -0800
committerFuwn <[email protected]>2025-11-20 19:17:14 -0800
commit9858b069ea4264840d98094e2e36ad2517f2215f (patch)
tree367ac8bcab6107ef8dfa4be524f834a5336d9bc3
parentfeat: Add Assignment 2 diagrams (diff)
downloadcst276-9858b069ea4264840d98094e2e36ad2517f2215f.tar.xz
cst276-9858b069ea4264840d98094e2e36ad2517f2215f.zip
feat: Implement Assignment 3 functionality
-rw-r--r--MorgSimulator/Dish.cs17
-rw-r--r--MorgSimulator/Factory/IMorgFactory.cs9
-rw-r--r--MorgSimulator/Factory/MorgFactory.cs6
-rw-r--r--MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs4
-rw-r--r--MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs4
-rw-r--r--MorgSimulator/Framework/Entity.cs85
-rw-r--r--MorgSimulator/Framework/EntityIterator.cs35
-rw-r--r--MorgSimulator/Framework/EntityReader.cs11
-rw-r--r--MorgSimulator/Framework/IEntityFactory.cs9
-rw-r--r--MorgSimulator/Framework/IEntityIterator.cs11
-rw-r--r--MorgSimulator/Framework/IFeedingStrategy.cs7
-rw-r--r--MorgSimulator/Framework/IMovementStrategy.cs7
-rw-r--r--MorgSimulator/Framework/Simulator.cs69
-rw-r--r--MorgSimulator/IFeedingStrategy.cs7
-rw-r--r--MorgSimulator/IMovementStrategy.cs7
-rw-r--r--MorgSimulator/Morg.cs82
-rw-r--r--MorgSimulator/MovementStrategy/MovementStrategyOozes.cs8
-rw-r--r--MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs8
-rw-r--r--MorgSimulator/Program.cs26
-rw-r--r--MorgSimulator/Reader/MorgReader.cs9
20 files changed, 268 insertions, 153 deletions
diff --git a/MorgSimulator/Dish.cs b/MorgSimulator/Dish.cs
index 1813d5a..38f1bc0 100644
--- a/MorgSimulator/Dish.cs
+++ b/MorgSimulator/Dish.cs
@@ -1,29 +1,26 @@
-using System.Collections.Generic;
-using System.Linq;
+using MorgSimulator.Framework;
namespace MorgSimulator
{
- public class Dish
+ public class Dish : Simulator<Morg>
{
- private readonly List<Morg> _morgs = [];
-
public void AddMorg(Morg morg)
{
- _morgs.Add(morg);
+ AddEntity(morg);
}
- public List<Morg> GetAllMorgs()
+ public System.Collections.Generic.List<Morg> GetAllMorgs()
{
- return [.. _morgs];
+ return [.. _entities];
}
#nullable enable
- public Morg? FindNearestPrey(Morg predator)
+ protected override Entity? FindNearestPrey(Morg predator)
{
Morg? nearestPrey = null;
double nearestDistance = double.MaxValue;
- foreach (var potentialPrey in _morgs)
+ foreach (var potentialPrey in _entities)
if (potentialPrey.IsAlive &&
potentialPrey != predator &&
predator.CanEat(potentialPrey.Type))
diff --git a/MorgSimulator/Factory/IMorgFactory.cs b/MorgSimulator/Factory/IMorgFactory.cs
deleted file mode 100644
index 60537de..0000000
--- a/MorgSimulator/Factory/IMorgFactory.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace MorgSimulator.Factory
-{
- public interface IMorgFactory
- {
- Morg CreateMorg(int id, string type, int x, int y, string movement, string feeding);
- IMovementStrategy CreateMovementStrategy(string movementType);
- IFeedingStrategy CreateFeedingStrategy(string behavior);
- }
-}
diff --git a/MorgSimulator/Factory/MorgFactory.cs b/MorgSimulator/Factory/MorgFactory.cs
index 95ecbee..3a6ef79 100644
--- a/MorgSimulator/Factory/MorgFactory.cs
+++ b/MorgSimulator/Factory/MorgFactory.cs
@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
-using System.Linq;
+using MorgSimulator.Framework;
namespace MorgSimulator.Factory
{
- public class MorgFactory : IMorgFactory
+ public class MorgFactory : IEntityFactory<Morg>
{
- public Morg CreateMorg(int id, string type, int x, int y, string movement, string feeding)
+ public Morg CreateEntity(int id, string type, int x, int y, string movement, string feeding)
{
var trimmedFeeding = feeding.Trim();
var feedingParts = trimmedFeeding.Split(' ');
diff --git a/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs b/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs
index 9e0f9a0..e5fb8c9 100644
--- a/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs
+++ b/MorgSimulator/FeedingStrategy/FeedingStrategyAbsorbs.cs
@@ -1,8 +1,10 @@
+using MorgSimulator.Framework;
+
namespace MorgSimulator
{
public class FeedingStrategyAbsorbs : IFeedingStrategy
{
- public void Feed(Morg predator, Morg prey)
+ public void Feed(Entity predator, Entity prey)
{
System.Console.WriteLine($"Morg {predator.Id} Absorbs Morg {prey.Id} at ({prey.Location.x},{prey.Location.y})");
diff --git a/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs b/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs
index d35227c..c5b96a3 100644
--- a/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs
+++ b/MorgSimulator/FeedingStrategy/FeedingStrategyEnvelops.cs
@@ -1,8 +1,10 @@
+using MorgSimulator.Framework;
+
namespace MorgSimulator
{
public class FeedingStrategyEnvelops : IFeedingStrategy
{
- public void Feed(Morg predator, Morg prey)
+ public void Feed(Entity predator, Entity prey)
{
System.Console.WriteLine($"Morg {predator.Id} Envelops Morg {prey.Id} at ({prey.Location.x},{prey.Location.y})");
diff --git a/MorgSimulator/Framework/Entity.cs b/MorgSimulator/Framework/Entity.cs
new file mode 100644
index 0000000..d415fdd
--- /dev/null
+++ b/MorgSimulator/Framework/Entity.cs
@@ -0,0 +1,85 @@
+using System.Collections.Generic;
+
+namespace MorgSimulator.Framework
+{
+ public abstract class Entity(int id, (int x, int y) location, (int x, int y) direction)
+ {
+ public int Id { get; set; } = id;
+ public string Type { get; set; } = string.Empty;
+ public (int x, int y) Location { get; set; } = location;
+ public (int x, int y) Direction { get; set; } = direction;
+ public bool IsAlive { get; set; } = true;
+ public IMovementStrategy MovementStrategy { get; set; } = null!;
+ public IFeedingStrategy FeedingStrategy { get; set; } = null!;
+ public List<string> PreyTypes { get; set; } = [];
+#nullable enable
+ public Entity? Prey { get; set; }
+#nullable disable
+
+ private readonly List<Entity> _observers = [];
+
+ public void Attach(Entity observer)
+ {
+ if (!_observers.Contains(observer))
+ _observers.Add(observer);
+ }
+
+ public void Detach(Entity observer)
+ {
+ _observers.Remove(observer);
+ }
+
+ public void Notify()
+ {
+ foreach (var observer in _observers)
+ observer.Update(this);
+ }
+
+ public virtual void Update(Entity subject)
+ {
+ Direction = CalculateDirectionToTarget(subject.Location);
+ }
+
+ public virtual void Move()
+ {
+ if (!IsAlive) return;
+
+ var newLocation = (Location.x + Direction.x, Location.y + Direction.y);
+
+ MovementStrategy.Move(this, newLocation);
+ Notify();
+ }
+
+ public virtual void Feed()
+ {
+ if (!IsAlive || Prey == null || !Prey.IsAlive) return;
+
+ FeedingStrategy.Feed(this, Prey);
+
+ Prey = null;
+ }
+
+ public bool CanEat(string targetType)
+ {
+ return PreyTypes.Contains(targetType);
+ }
+
+ public (int x, int y) CalculateDirectionToTarget((int x, int y) target)
+ {
+ int deltaX = target.x - Location.x;
+ int deltaY = target.y - Location.y;
+ int directionX = deltaX > 0 ? 1 : (deltaX < 0 ? -1 : 0);
+ int directionY = deltaY > 0 ? 1 : (deltaY < 0 ? -1 : 0);
+
+ return (directionX, directionY);
+ }
+
+ public double DistanceTo((int x, int y) target)
+ {
+ int deltaX = target.x - Location.x;
+ int deltaY = target.y - Location.y;
+
+ return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
+ }
+ }
+}
diff --git a/MorgSimulator/Framework/EntityIterator.cs b/MorgSimulator/Framework/EntityIterator.cs
new file mode 100644
index 0000000..84976c7
--- /dev/null
+++ b/MorgSimulator/Framework/EntityIterator.cs
@@ -0,0 +1,35 @@
+#nullable enable
+using System.Collections.Generic;
+
+namespace MorgSimulator.Framework
+{
+ public class EntityIterator<T> : IEntityIterator<T> where T : Entity
+ {
+ private readonly List<T> _entities;
+ private int _currentIndex = 0;
+
+ public EntityIterator(List<T> entities)
+ {
+ _entities = entities;
+ }
+
+ public bool HasNext()
+ {
+ return _currentIndex < _entities.Count;
+ }
+
+ public T? Next()
+ {
+ if (!HasNext())
+ return null;
+
+ return _entities[_currentIndex++];
+ }
+
+ public void Reset()
+ {
+ _currentIndex = 0;
+ }
+ }
+}
+#nullable disable
diff --git a/MorgSimulator/Framework/EntityReader.cs b/MorgSimulator/Framework/EntityReader.cs
new file mode 100644
index 0000000..b3c2fbd
--- /dev/null
+++ b/MorgSimulator/Framework/EntityReader.cs
@@ -0,0 +1,11 @@
+#nullable enable
+namespace MorgSimulator.Framework
+{
+ public abstract class EntityReader<T>(Reader.Reader reader, IEntityFactory<T> factory) : Reader.ReaderDecorator(reader) where T : Entity
+ {
+ protected readonly IEntityFactory<T> _factory = factory;
+
+ public abstract T? ReadEntity(int id);
+ }
+}
+#nullable disable
diff --git a/MorgSimulator/Framework/IEntityFactory.cs b/MorgSimulator/Framework/IEntityFactory.cs
new file mode 100644
index 0000000..37da19d
--- /dev/null
+++ b/MorgSimulator/Framework/IEntityFactory.cs
@@ -0,0 +1,9 @@
+namespace MorgSimulator.Framework
+{
+ public interface IEntityFactory<T> where T : Entity
+ {
+ T CreateEntity(int id, string type, int x, int y, string movement, string feeding);
+ IMovementStrategy CreateMovementStrategy(string movementType);
+ IFeedingStrategy CreateFeedingStrategy(string behavior);
+ }
+}
diff --git a/MorgSimulator/Framework/IEntityIterator.cs b/MorgSimulator/Framework/IEntityIterator.cs
new file mode 100644
index 0000000..9333468
--- /dev/null
+++ b/MorgSimulator/Framework/IEntityIterator.cs
@@ -0,0 +1,11 @@
+#nullable enable
+namespace MorgSimulator.Framework
+{
+ public interface IEntityIterator<T> where T : Entity
+ {
+ bool HasNext();
+ T? Next();
+ void Reset();
+ }
+}
+#nullable disable
diff --git a/MorgSimulator/Framework/IFeedingStrategy.cs b/MorgSimulator/Framework/IFeedingStrategy.cs
new file mode 100644
index 0000000..cbbe315
--- /dev/null
+++ b/MorgSimulator/Framework/IFeedingStrategy.cs
@@ -0,0 +1,7 @@
+namespace MorgSimulator.Framework
+{
+ public interface IFeedingStrategy
+ {
+ void Feed(Entity predator, Entity prey);
+ }
+}
diff --git a/MorgSimulator/Framework/IMovementStrategy.cs b/MorgSimulator/Framework/IMovementStrategy.cs
new file mode 100644
index 0000000..bb8d13d
--- /dev/null
+++ b/MorgSimulator/Framework/IMovementStrategy.cs
@@ -0,0 +1,7 @@
+namespace MorgSimulator.Framework
+{
+ public interface IMovementStrategy
+ {
+ void Move(Entity entity, (int x, int y) newLocation);
+ }
+}
diff --git a/MorgSimulator/Framework/Simulator.cs b/MorgSimulator/Framework/Simulator.cs
new file mode 100644
index 0000000..6e8c694
--- /dev/null
+++ b/MorgSimulator/Framework/Simulator.cs
@@ -0,0 +1,69 @@
+using System.Collections.Generic;
+
+namespace MorgSimulator.Framework
+{
+ public abstract class Simulator<T> where T : Entity
+ {
+ protected readonly List<T> _entities = [];
+ protected const double FEEDING_DISTANCE = 1.0;
+
+ public void AddEntity(T entity)
+ {
+ _entities.Add(entity);
+ }
+
+ public IEnumerable<T> GetAllEntities()
+ {
+ return _entities;
+ }
+
+ public IEntityIterator<T> CreateIterator()
+ {
+ return new EntityIterator<T>(_entities);
+ }
+
+ public void Run(int runTime)
+ {
+ for (int timeStep = 0; timeStep < runTime; timeStep++)
+ ProcessTimeStep();
+ }
+
+ protected virtual void ProcessTimeStep()
+ {
+ foreach (var entity in _entities)
+ if (entity.IsAlive)
+ {
+ FindPreyIfNeeded(entity);
+ entity.Move();
+ CheckAndFeed(entity);
+ }
+ }
+
+ protected virtual void FindPreyIfNeeded(T entity)
+ {
+ if (entity.Prey == null || !entity.Prey.IsAlive)
+ {
+ var nearestPrey = FindNearestPrey(entity);
+
+ if (nearestPrey != null)
+ {
+ nearestPrey.Attach(entity);
+
+ entity.Prey = nearestPrey as T;
+ entity.Direction = entity.CalculateDirectionToTarget(nearestPrey.Location);
+ }
+ }
+ }
+
+ protected virtual void CheckAndFeed(T entity)
+ {
+ if (entity.Prey != null && entity.Prey.IsAlive &&
+ entity.DistanceTo(entity.Prey.Location) <= FEEDING_DISTANCE)
+ entity.Feed();
+ }
+
+#nullable enable
+ protected abstract Entity? FindNearestPrey(T predator);
+#nullable disable
+ }
+}
diff --git a/MorgSimulator/IFeedingStrategy.cs b/MorgSimulator/IFeedingStrategy.cs
deleted file mode 100644
index b0344ea..0000000
--- a/MorgSimulator/IFeedingStrategy.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MorgSimulator
-{
- public interface IFeedingStrategy
- {
- void Feed(Morg predator, Morg prey);
- }
-}
diff --git a/MorgSimulator/IMovementStrategy.cs b/MorgSimulator/IMovementStrategy.cs
deleted file mode 100644
index 2b073e1..0000000
--- a/MorgSimulator/IMovementStrategy.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace MorgSimulator
-{
- public interface IMovementStrategy
- {
- void Move(Morg morg, (int x, int y) newLocation);
- }
-}
diff --git a/MorgSimulator/Morg.cs b/MorgSimulator/Morg.cs
index cfac9dd..ba91564 100644
--- a/MorgSimulator/Morg.cs
+++ b/MorgSimulator/Morg.cs
@@ -1,87 +1,9 @@
-using System.Collections.Generic;
-using System.Linq;
+using MorgSimulator.Framework;
namespace MorgSimulator
{
public class Morg(int id, (int x, int y) location, (int x, int y) direction)
+ : Entity(id, location, direction)
{
- public int Id { get; set; } = id;
- public string Type { get; set; } = string.Empty;
- public (int x, int y) Location { get; set; } = location;
- public (int x, int y) Direction { get; set; } = direction;
- public bool IsAlive { get; set; } = true;
- public IMovementStrategy MovementStrategy { get; set; } = null!;
- public IFeedingStrategy FeedingStrategy { get; set; } = null!;
- public List<string> PreyTypes { get; set; } = [];
-#nullable enable
- public Morg? Prey { get; set; }
-#nullable disable
-
- private readonly List<Morg> _observers = [];
-
- public void Attach(Morg observer)
- {
- if (!_observers.Contains(observer))
- _observers.Add(observer);
- }
-
- public void Detach(Morg observer)
- {
- _observers.Remove(observer);
- }
-
- public void Notify()
- {
- foreach (var observer in _observers)
- observer.Update(this);
- }
-
- public void Update(Morg subject)
- {
- Direction = CalculateDirectionToTarget(subject.Location);
- }
-
- public void Move()
- {
- if (!IsAlive) return;
-
- var newLocation = (Location.x + Direction.x, Location.y + Direction.y);
-
- MovementStrategy.Move(this, newLocation);
- Notify();
- }
-
- public void Feed()
- {
- if (!IsAlive || Prey == null || !Prey.IsAlive) return;
-
- FeedingStrategy.Feed(this, Prey);
-
- Prey = null;
- }
-
- public bool CanEat(string targetType)
- {
- return PreyTypes.Contains(targetType);
- }
-
- public (int x, int y) CalculateDirectionToTarget((int x, int y) target)
- {
- int deltaX = target.x - Location.x;
- int deltaY = target.y - Location.y;
- int directionX = deltaX > 0 ? 1 : (deltaX < 0 ? -1 : 0);
- int directionY = deltaY > 0 ? 1 : (deltaY < 0 ? -1 : 0);
-
- return (directionX, directionY);
- }
-
- public double DistanceTo((int x, int y) target)
- {
- int deltaX = target.x - Location.x;
- int deltaY = target.y - Location.y;
-
- return System.Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
- }
-
}
} \ No newline at end of file
diff --git a/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs b/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs
index 217d175..dfc8423 100644
--- a/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs
+++ b/MorgSimulator/MovementStrategy/MovementStrategyOozes.cs
@@ -1,12 +1,14 @@
+using MorgSimulator.Framework;
+
namespace MorgSimulator
{
public class MovementStrategyOozes : IMovementStrategy
{
- public void Move(Morg morg, (int x, int y) newLocation)
+ public void Move(Entity entity, (int x, int y) newLocation)
{
- System.Console.WriteLine($"Morg {morg.Id} Oozes from ({morg.Location.x},{morg.Location.y}) to ({newLocation.x},{newLocation.y})");
+ System.Console.WriteLine($"Morg {entity.Id} Oozes from ({entity.Location.x},{entity.Location.y}) to ({newLocation.x},{newLocation.y})");
- morg.Location = newLocation;
+ entity.Location = newLocation;
}
}
}
diff --git a/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs b/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs
index efdd3ef..ddbfe8c 100644
--- a/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs
+++ b/MorgSimulator/MovementStrategy/MovementStrategyPaddles.cs
@@ -1,12 +1,14 @@
+using MorgSimulator.Framework;
+
namespace MorgSimulator
{
public class MovementStrategyPaddles : IMovementStrategy
{
- public void Move(Morg morg, (int x, int y) newLocation)
+ public void Move(Entity entity, (int x, int y) newLocation)
{
- System.Console.WriteLine($"Morg {morg.Id} Paddles from ({morg.Location.x},{morg.Location.y}) to ({newLocation.x},{newLocation.y})");
+ System.Console.WriteLine($"Morg {entity.Id} Paddles from ({entity.Location.x},{entity.Location.y}) to ({newLocation.x},{newLocation.y})");
- morg.Location = newLocation;
+ entity.Location = newLocation;
}
}
}
diff --git a/MorgSimulator/Program.cs b/MorgSimulator/Program.cs
index 29fd971..3cb336b 100644
--- a/MorgSimulator/Program.cs
+++ b/MorgSimulator/Program.cs
@@ -11,7 +11,7 @@ int id = 1;
while (!morgReader.EndOfStream)
{
- var morg = morgReader.ReadMorg(id++);
+ var morg = morgReader.ReadEntity(id++);
if (morg != null)
dish.AddMorg(morg);
@@ -21,26 +21,4 @@ morgReader.Close();
const int RUN_TIME = 15;
-for (int timeStep = 0; timeStep < RUN_TIME; timeStep++)
- foreach (var morg in dish.GetAllMorgs())
- if (morg.IsAlive)
- {
- if (morg.Prey == null || !morg.Prey.IsAlive)
- {
- var nearestPrey = dish.FindNearestPrey(morg);
-
- if (nearestPrey != null)
- {
- nearestPrey.Attach(morg);
-
- morg.Prey = nearestPrey;
- morg.Direction = morg.CalculateDirectionToTarget(nearestPrey.Location);
- }
- }
-
- morg.Move();
- morg.Notify();
-
- if (morg.Prey != null && morg.Prey.IsAlive && morg.DistanceTo(morg.Prey.Location) <= 1.0)
- morg.Feed();
- }
+dish.Run(RUN_TIME);
diff --git a/MorgSimulator/Reader/MorgReader.cs b/MorgSimulator/Reader/MorgReader.cs
index 2bf9a30..56c229b 100644
--- a/MorgSimulator/Reader/MorgReader.cs
+++ b/MorgSimulator/Reader/MorgReader.cs
@@ -1,13 +1,12 @@
#nullable enable
using MorgSimulator.Factory;
+using MorgSimulator.Framework;
namespace MorgSimulator.Reader
{
- public class MorgReader(Reader reader, IMorgFactory factory) : ReaderDecorator(reader)
+ public class MorgReader(Reader reader, IEntityFactory<Morg> factory) : EntityReader<Morg>(reader, factory)
{
- private readonly IMorgFactory _factory = factory;
-
- public Morg? ReadMorg(int id)
+ public override Morg? ReadEntity(int id)
{
if (_reader is not CSVReader csvReader) return null;
@@ -25,7 +24,7 @@ namespace MorgSimulator.Reader
!int.TryParse(yString, out int y))
return null;
- return _factory.CreateMorg(id, type, x, y, movement, feeding);
+ return _factory.CreateEntity(id, type, x, y, movement, feeding);
}
}
}