-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
236 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
using System.Collections; | ||
|
||
namespace DateRecurrenceR.Collections; | ||
|
||
internal struct UnionEnumerator : IEnumerator<DateOnly> | ||
{ | ||
private readonly EWrapper[] _enumerators; | ||
private DateOnly? _current = null; | ||
|
||
public UnionEnumerator(IReadOnlyList<IEnumerator<DateOnly>> enumerators) | ||
{ | ||
var hash = new HashSet<EWrapper>(); | ||
|
||
for (var i = 0; i < enumerators.Count; i++) | ||
{ | ||
if (enumerators[i] is UnionEnumerator ue) | ||
{ | ||
for (var j = 0; j < ue._enumerators.Length; j++) | ||
{ | ||
hash.Add(ue._enumerators[j]); | ||
} | ||
} | ||
else | ||
{ | ||
hash.Add(new EWrapper(enumerators[i])); | ||
} | ||
} | ||
|
||
_enumerators = hash.ToArray(); | ||
|
||
Current = default; | ||
} | ||
|
||
public bool MoveNext() | ||
{ | ||
var nextIndex = -1; | ||
|
||
for (var i = 0; i < _enumerators.Length; i++) | ||
{ | ||
if (_current.HasValue) | ||
{ | ||
while (_enumerators[i].CanMoveNext && _enumerators[i].Enum.Current <= _current.Value) | ||
{ | ||
_enumerators[i].MoveNext(); | ||
} | ||
} | ||
else | ||
{ | ||
_enumerators[i].MoveNext(); | ||
} | ||
} | ||
|
||
for (var i = 0; i < _enumerators.Length; i++) | ||
{ | ||
if (!_enumerators[i].CanMoveNext) continue; | ||
|
||
_current = _enumerators[i].Enum.Current; | ||
nextIndex = i; | ||
break; | ||
} | ||
|
||
for (var i = 0; i < _enumerators.Length; i++) | ||
{ | ||
if (!_enumerators[i].CanMoveNext || !(_current > _enumerators[i].Enum.Current)) continue; | ||
|
||
_current = _enumerators[i].Enum.Current; | ||
nextIndex = i; | ||
} | ||
|
||
if (nextIndex < 0) | ||
{ | ||
return false; | ||
} | ||
|
||
Current = _enumerators[nextIndex].Enum.Current; | ||
|
||
return true; | ||
} | ||
|
||
public void Reset() | ||
{ | ||
throw new NotSupportedException(); | ||
} | ||
|
||
public DateOnly Current { get; private set; } | ||
|
||
object IEnumerator.Current => Current; | ||
|
||
public void Dispose() | ||
{ | ||
} | ||
|
||
private struct EWrapper | ||
{ | ||
public EWrapper(IEnumerator<DateOnly> @enum) | ||
{ | ||
Enum = @enum; | ||
CanMoveNext = true; | ||
} | ||
|
||
public IEnumerator<DateOnly> Enum { get; } | ||
public bool CanMoveNext { get; private set; } | ||
|
||
public bool MoveNext() | ||
{ | ||
CanMoveNext = Enum.MoveNext(); | ||
return CanMoveNext; | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Enum.GetHashCode(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
#if NET8_0 | ||
#if NET8_0_OR_GREATER | ||
namespace DateRecurrenceR; | ||
|
||
[System.Runtime.CompilerServices.InlineArray(7)] | ||
|
101 changes: 101 additions & 0 deletions
101
test/DateRecurrenceR.Tests.Unit/Collections/UnionEnumeratorTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using DateRecurrenceR.Collections; | ||
using DateRecurrenceR.Core; | ||
using FluentAssertions; | ||
using JetBrains.Annotations; | ||
|
||
namespace DateRecurrenceR.Tests.Unit.Collections; | ||
|
||
[TestSubject(typeof(UnionEnumerator))] | ||
public class UnionEnumeratorTest | ||
{ | ||
[Fact] | ||
public void Union_two_recurrences() | ||
{ | ||
// Arrange | ||
const int takeCount = 5; | ||
var interval = new Interval(1); | ||
var beginDate = DateOnly.MinValue; | ||
var fromDate = beginDate; | ||
|
||
var enumerator1 = Recurrence.Yearly(beginDate, fromDate, takeCount, new DayOfYear(1), interval); | ||
var enumerator2 = Recurrence.Yearly(beginDate, fromDate, takeCount, new DayOfYear(2), interval); | ||
|
||
var res = Recurrence.Union(enumerator1, enumerator2); | ||
|
||
// Act | ||
var list = new List<DateOnly>(); | ||
|
||
while (res.MoveNext()) | ||
{ | ||
list.Add(res.Current); | ||
} | ||
|
||
//Assert | ||
list.Count.Should().Be(takeCount * 2); | ||
} | ||
|
||
[Fact] | ||
public void Union_one_recurrence_multiple_times() | ||
{ | ||
// Arrange | ||
const int takeCount = 5; | ||
var dayOfYear = new DayOfYear(256); | ||
var interval = new Interval(1); | ||
var beginDate = DateOnly.MinValue; | ||
var fromDate = beginDate; | ||
|
||
var equivalentEnumerator = Recurrence.Yearly(beginDate, fromDate, takeCount, dayOfYear, interval); | ||
var enumerator = Recurrence.Yearly(beginDate, fromDate, takeCount, dayOfYear, interval); | ||
|
||
var res = Recurrence.Union(enumerator, enumerator, enumerator, enumerator); | ||
res = Recurrence.Union(res, enumerator, enumerator, enumerator); | ||
res = Recurrence.Union(res, enumerator, enumerator); | ||
res = Recurrence.Union(res, enumerator); | ||
|
||
// Act | ||
var equivalentList = new List<DateOnly>(); | ||
while (equivalentEnumerator.MoveNext()) | ||
{ | ||
equivalentList.Add(equivalentEnumerator.Current); | ||
} | ||
|
||
var list = new List<DateOnly>(); | ||
while (res.MoveNext()) | ||
{ | ||
list.Add(res.Current); | ||
} | ||
|
||
//Assert | ||
list.Count.Should().Be(takeCount); | ||
list.Should().BeEquivalentTo(equivalentList); | ||
} | ||
|
||
[Fact] | ||
public void Union_two_recurrence_multiple_times() | ||
{ | ||
// Arrange | ||
const int takeCount = 5; | ||
var interval = new Interval(1); | ||
var beginDate = DateOnly.MinValue; | ||
var fromDate = beginDate; | ||
|
||
var enumerator1 = Recurrence.Yearly(beginDate, fromDate, takeCount, new DayOfYear(1), interval); | ||
var enumerator2 = Recurrence.Yearly(beginDate, fromDate, takeCount, new DayOfYear(2), interval); | ||
|
||
var res1 = Recurrence.Union(enumerator1, enumerator1, enumerator1, enumerator1); | ||
var res2 = Recurrence.Union(enumerator2, enumerator2, enumerator2, enumerator2); | ||
var res = Recurrence.Union(res1, res2); | ||
res = Recurrence.Union(res, res1, enumerator2, enumerator1); | ||
res = Recurrence.Union(res, res2, enumerator1, enumerator2); | ||
|
||
// Act | ||
var list = new List<DateOnly>(); | ||
while (res.MoveNext()) | ||
{ | ||
list.Add(res.Current); | ||
} | ||
|
||
//Assert | ||
list.Count.Should().Be(takeCount * 2); | ||
} | ||
} |
2 changes: 1 addition & 1 deletion
2
test/DateRecurrenceR.Tests.Unit/DateRecurrenceR.Tests.Unit.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters