Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix blackouts feature error and add new unit tests #41

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 84 additions & 40 deletions Assets/Scripts/Lights.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@
using System.Collections.Generic;

/// <summary>
/// Facilitates the management and retrieval of Fade components associated with a collection of GameObjects, black screens.
/// Script for handling the lights in the environment (blackouts).
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
/// </summary>
namespace Lights
{
public class InfiniteEnumerator : IEnumerator<int>
{
private int _initialValue;
private int _currentValue;
private readonly int _initialValue = 0;
private int _currentValue = 0;

public InfiniteEnumerator(int initialValue = 0)
public InfiniteEnumerator() { }

public InfiniteEnumerator(int initialValue)
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
{
_initialValue = initialValue;
_currentValue = 0;
Expand All @@ -29,70 +31,112 @@ public void Reset()
_currentValue = 0;
}

public int Current => _currentValue;
public int Current
{
get { return _currentValue; }
}
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved

object IEnumerator.Current => Current;
object IEnumerator.Current
{
get { return Current; }
}

public void Dispose() { }
void IDisposable.Dispose() { }
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
}

public class LightsSwitch
{
private int _episodeLength;
private readonly int _episodeLength = 0;
private bool _lightStatus = true;
private List<int> _blackouts;
private IEnumerator<int> _blackoutsEnum;
private readonly List<int> _blackouts = new List<int>();
private readonly IEnumerator<int> _blackoutsEnum;
private int _nextFrameSwitch = -1;

public LightsSwitch(int episodeLength = 0, List<int> blackouts = null)
public LightsSwitch()
{
if (episodeLength < 0)
throw new ArgumentException("Episode length cannot be negative.");

_episodeLength = episodeLength;
_blackouts = blackouts ?? new List<int>();
_blackoutsEnum = _blackouts.GetEnumerator();
}

if (_blackouts.Count > 0)
public LightsSwitch(int episodeLength, List<int> blackouts)
{
try
{
foreach (var blackout in _blackouts)
if (episodeLength < 0)
{
if (blackout < 0 || blackout >= _episodeLength)
throw new ArgumentException("Blackout interval is invalid.");
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
throw new ArgumentException("Episode length (timeLimit) cannot be negative.");
}

_blackouts.Sort();
_episodeLength = episodeLength;
_blackouts = blackouts ?? throw new ArgumentNullException(nameof(blackouts));

if (_blackouts.Count > 1)
{
for (int i = 1; i < _blackouts.Count; i++)
{
if (_blackouts[i] <= _blackouts[i - 1])
{
throw new ArgumentException("Invalid blackout sequence: values must be in strictly increasing order.");
}
}
}

_blackoutsEnum =
_blackouts[0] < 0
? new InfiniteEnumerator(-_blackouts[0])
: _blackouts.GetEnumerator();
if (_blackouts.Count > 0 && _blackouts[0] < 0)
{
_blackoutsEnum = new InfiniteEnumerator(-_blackouts[0]);
}
else
{
_blackoutsEnum = _blackouts.GetEnumerator();
}
Reset();
}
else
catch (Exception ex)
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
{
_blackoutsEnum = _blackouts.GetEnumerator();
Console.WriteLine($"Error initialising lightSwitch: {ex.Message}");
throw;
}

Reset();
}

public void Reset()
{
_lightStatus = true;
_blackoutsEnum.Reset();
_nextFrameSwitch = _blackoutsEnum.MoveNext() ? _blackoutsEnum.Current : -1;
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
try
{
_lightStatus = true;
_blackoutsEnum.Reset();
if (_blackoutsEnum.MoveNext())
{
_nextFrameSwitch = _blackoutsEnum.Current;
}
else
{
_nextFrameSwitch = -1;
}
}
catch (Exception ex)
{
Console.WriteLine($"Error resetting LightsSwitch (blackouts): {ex.Message}");
throw;
}
}

public bool LightStatus(int step, int agentDecisionInterval)
{
if (step < 0 || agentDecisionInterval <= 0)
throw new ArgumentException("Step and agent decision interval must be positive.");

if (step == _nextFrameSwitch * agentDecisionInterval)
try
{
if (step == _nextFrameSwitch * agentDecisionInterval)
{
_lightStatus = !_lightStatus;
if (_blackoutsEnum.MoveNext())
{
_nextFrameSwitch = _blackoutsEnum.Current;
}
}
return _lightStatus;
}
catch (Exception ex)
{
_lightStatus = !_lightStatus;
_nextFrameSwitch = _blackoutsEnum.MoveNext() ? _blackoutsEnum.Current : -1;
Console.WriteLine($"Error in LightStatus (blackouts): {ex.Message}");
return _lightStatus;
}
return _lightStatus;
}
}
}
92 changes: 54 additions & 38 deletions Assets/Tests/EditMode/LightSwitchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
public class LightsSwitchTests
{
[Test]
public void IncrementValueOnMoveNext()
public void InfiniteEnumerator_IncrementValueOnMoveNext()
{
int initialValue = 3;
var enumerator = new InfiniteEnumerator(initialValue);

var enumerator = new InfiniteEnumerator(3);
enumerator.MoveNext();
int currentValue = enumerator.Current;
Assert.AreEqual(3, enumerator.Current);
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
}

Assert.AreEqual(initialValue, currentValue);
[Test]
public void LightsSwitch_ThrowExceptionForNegativeEpisodeLength()
{
Assert.Throws<ArgumentException>(() => new LightsSwitch(-10, new List<int> { 1, 2, 3 }));
}

[Test]
Expand All @@ -34,61 +36,75 @@ public void ResetEnumeratorToZero()
}

[Test]
public void KeepIncrementingOnMultipleMoveNext()
public void InfiniteEnumerator_ResetToZero()
{
int initialValue = 2;
var enumerator = new InfiniteEnumerator(initialValue);

enumerator.MoveNext();
Assert.AreEqual(2, enumerator.Current);

var enumerator = new InfiniteEnumerator(5);
enumerator.MoveNext();
Assert.AreEqual(4, enumerator.Current);
enumerator.Reset();
Assert.AreEqual(0, enumerator.Current);
}

enumerator.MoveNext();
Assert.AreEqual(6, enumerator.Current);
[Test]
public void LightsSwitch_InitializeWithValidParameters()
{
var lightsSwitch = new LightsSwitch(10, new List<int> { 1, 2, 3 });
Assert.DoesNotThrow(() => lightsSwitch.Reset());
}

[Test]
public void ThrowExceptionForNegativeEpisodeLength()
public void LightsSwitch_HandleInfiniteBlackouts()
{
Assert.Throws<ArgumentException>(() => new LightsSwitch(-1, new List<int> { 1 }));
var lightsSwitch = new LightsSwitch(10, new List<int> { -2 });
Assert.IsTrue(lightsSwitch.LightStatus(0, 1));
Assert.IsFalse(lightsSwitch.LightStatus(2, 1));
Assert.IsTrue(lightsSwitch.LightStatus(4, 1));
}

[Test]
public void ThrowExceptionForInvalidBlackoutInterval()
public void LightsSwitch_ResetBehavior()
{
Assert.Throws<ArgumentException>(() => new LightsSwitch(5, new List<int> { -1, 6 }));
var lightsSwitch = new LightsSwitch(10, new List<int> { 1, 3 });
lightsSwitch.LightStatus(1, 1);
lightsSwitch.Reset();
Assert.IsTrue(lightsSwitch.LightStatus(0, 1));
}

[Test]
public void ReturnTrueIfNoBlackouts()
public void LightsSwitch_HandleEmptyBlackoutList()
{
var lightsSwitch = new LightsSwitch(10, new List<int>());

bool lightStatus = lightsSwitch.LightStatus(0, 1);

Assert.IsTrue(lightStatus);
Assert.IsTrue(lightsSwitch.LightStatus(0, 1));
Assert.IsTrue(lightsSwitch.LightStatus(5, 1));
}

[Test]
public void HandleMultipleBlackoutsProperly()
public void LightsSwitch_HandleDifferentAgentDecisionIntervals()
{
var blackouts = new List<int> { 1, 2, 3 };
var lightsSwitch = new LightsSwitch(10, blackouts);

Assert.IsTrue(lightsSwitch.LightStatus(0, 1));
Assert.IsFalse(lightsSwitch.LightStatus(1, 1));
Assert.IsTrue(lightsSwitch.LightStatus(2, 1));
Assert.IsFalse(lightsSwitch.LightStatus(3, 1));
var lightsSwitch = new LightsSwitch(20, new List<int> { 2, 4 });
Assert.IsTrue(lightsSwitch.LightStatus(0, 2));
Assert.IsFalse(lightsSwitch.LightStatus(4, 2));
Assert.IsTrue(lightsSwitch.LightStatus(8, 2));
}

[Test]
public void ThrowExceptionForInvalidStepOrAgentDecisionInterval()
public void LightsSwitch_ThrowExceptionForInvalidBlackoutSequence()
{
var lightsSwitch = new LightsSwitch(10, new List<int> { 1 });
Assert.Throws<ArgumentException>(() => new LightsSwitch(20, new List<int> { 10, 1 }));
}

Assert.Throws<ArgumentException>(() => lightsSwitch.LightStatus(-1, 1));
Assert.Throws<ArgumentException>(() => lightsSwitch.LightStatus(1, 0));
[Test]
public void LightsSwitch_HandleInfiniteBlackoutsWithNegativeNumber()
{
var lightsSwitch = new LightsSwitch(100, new List<int> { -20 });
Assert.IsTrue(lightsSwitch.LightStatus(0, 1));
Assert.IsTrue(lightsSwitch.LightStatus(19, 1));
Assert.IsFalse(lightsSwitch.LightStatus(20, 1));
Assert.IsFalse(lightsSwitch.LightStatus(39, 1));
Assert.IsTrue(lightsSwitch.LightStatus(40, 1));
Assert.IsTrue(lightsSwitch.LightStatus(59, 1));
Assert.IsFalse(lightsSwitch.LightStatus(60, 1));
Assert.IsFalse(lightsSwitch.LightStatus(79, 1));
Assert.IsTrue(lightsSwitch.LightStatus(80, 1));
alhasacademy96 marked this conversation as resolved.
Show resolved Hide resolved
}
}

}