mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
190 lines
6.9 KiB
C#
190 lines
6.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using Artemis.Storage.Entities.Profile.Abstract;
|
|
using Artemis.Storage.Entities.Profile.Conditions;
|
|
|
|
namespace Artemis.Core
|
|
{
|
|
/// <summary>
|
|
/// A group containing zero to many <see cref="DataModelConditionPart" />s which it evaluates using a boolean specific
|
|
/// operator
|
|
/// </summary>
|
|
public class DataModelConditionGroup : DataModelConditionPart
|
|
{
|
|
private bool _disposed;
|
|
|
|
/// <summary>
|
|
/// Creates a new instance of the <see cref="DataModelConditionGroup" /> class
|
|
/// </summary>
|
|
/// <param name="parent"></param>
|
|
public DataModelConditionGroup(DataModelConditionPart? parent)
|
|
{
|
|
Parent = parent;
|
|
Entity = new DataModelConditionGroupEntity();
|
|
ChildAdded += OnChildrenChanged;
|
|
ChildRemoved += OnChildrenChanged;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new instance of the <see cref="DataModelConditionGroup" /> class
|
|
/// </summary>
|
|
/// <param name="parent"></param>
|
|
/// <param name="entity"></param>
|
|
public DataModelConditionGroup(DataModelConditionPart? parent, DataModelConditionGroupEntity entity)
|
|
{
|
|
Parent = parent;
|
|
Entity = entity;
|
|
BooleanOperator = (BooleanOperator) Entity.BooleanOperator;
|
|
|
|
foreach (DataModelConditionPartEntity childEntity in Entity.Children)
|
|
{
|
|
if (childEntity is DataModelConditionGroupEntity groupEntity)
|
|
AddChild(new DataModelConditionGroup(this, groupEntity));
|
|
else if (childEntity is DataModelConditionListEntity listEntity)
|
|
AddChild(new DataModelConditionList(this, listEntity));
|
|
else if (childEntity is DataModelConditionEventEntity eventEntity)
|
|
AddChild(new DataModelConditionEvent(this, eventEntity));
|
|
else if (childEntity is DataModelConditionGeneralPredicateEntity predicateEntity)
|
|
AddChild(new DataModelConditionGeneralPredicate(this, predicateEntity));
|
|
else if (childEntity is DataModelConditionListPredicateEntity listPredicateEntity)
|
|
AddChild(new DataModelConditionListPredicate(this, listPredicateEntity));
|
|
else if (childEntity is DataModelConditionEventPredicateEntity eventPredicateEntity)
|
|
AddChild(new DataModelConditionEventPredicate(this, eventPredicateEntity));
|
|
}
|
|
|
|
ContainsEvents = Children.Any(c => c is DataModelConditionEvent);
|
|
ChildAdded += OnChildrenChanged;
|
|
ChildRemoved += OnChildrenChanged;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the boolean operator of this group
|
|
/// </summary>
|
|
public BooleanOperator BooleanOperator { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets whether this group contains any events
|
|
/// </summary>
|
|
public bool ContainsEvents { get; private set; }
|
|
|
|
internal DataModelConditionGroupEntity Entity { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
public override bool Evaluate()
|
|
{
|
|
if (_disposed)
|
|
throw new ObjectDisposedException("DataModelConditionGroup");
|
|
|
|
// Empty groups are always true
|
|
if (Children.Count == 0)
|
|
return true;
|
|
// Groups with only one child ignore the boolean operator
|
|
if (Children.Count == 1)
|
|
return Children[0].Evaluate();
|
|
|
|
if (ContainsEvents)
|
|
{
|
|
bool eventTriggered = Children.Where(c => c is DataModelConditionEvent).Any(c => c.Evaluate());
|
|
return eventTriggered && EvaluateWithOperator(Children.Where(c => !(c is DataModelConditionEvent)));
|
|
}
|
|
return EvaluateWithOperator(Children);
|
|
}
|
|
|
|
private bool EvaluateWithOperator(IEnumerable<DataModelConditionPart> targets)
|
|
{
|
|
return BooleanOperator switch
|
|
{
|
|
BooleanOperator.And => targets.All(c => c.Evaluate()),
|
|
BooleanOperator.Or => targets.Any(c => c.Evaluate()),
|
|
BooleanOperator.AndNot => targets.All(c => !c.Evaluate()),
|
|
BooleanOperator.OrNot => targets.Any(c => !c.Evaluate()),
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
};
|
|
}
|
|
|
|
#region IDisposable
|
|
|
|
/// <inheritdoc />
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
_disposed = true;
|
|
foreach (DataModelConditionPart child in Children)
|
|
child.Dispose();
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <inheritdoc />
|
|
internal override bool EvaluateObject(object? target)
|
|
{
|
|
if (_disposed)
|
|
throw new ObjectDisposedException("DataModelConditionGroup");
|
|
|
|
// Empty groups are always true
|
|
if (Children.Count == 0)
|
|
return true;
|
|
// Groups with only one child ignore the boolean operator
|
|
if (Children.Count == 1)
|
|
return Children[0].EvaluateObject(target);
|
|
|
|
return BooleanOperator switch
|
|
{
|
|
BooleanOperator.And => Children.All(c => c.EvaluateObject(target)),
|
|
BooleanOperator.Or => Children.Any(c => c.EvaluateObject(target)),
|
|
BooleanOperator.AndNot => Children.All(c => !c.EvaluateObject(target)),
|
|
BooleanOperator.OrNot => Children.Any(c => !c.EvaluateObject(target)),
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
};
|
|
}
|
|
|
|
internal override void Save()
|
|
{
|
|
Entity.BooleanOperator = (int) BooleanOperator;
|
|
|
|
Entity.Children.Clear();
|
|
Entity.Children.AddRange(Children.Select(c => c.GetEntity()));
|
|
foreach (DataModelConditionPart child in Children)
|
|
child.Save();
|
|
}
|
|
|
|
internal override DataModelConditionPartEntity GetEntity()
|
|
{
|
|
return Entity;
|
|
}
|
|
|
|
private void OnChildrenChanged(object? sender, EventArgs e)
|
|
{
|
|
ContainsEvents = Children.Any(c => c is DataModelConditionEvent);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a boolean operator
|
|
/// </summary>
|
|
public enum BooleanOperator
|
|
{
|
|
/// <summary>
|
|
/// All the conditions in the group should evaluate to true
|
|
/// </summary>
|
|
And,
|
|
|
|
/// <summary>
|
|
/// Any of the conditions in the group should evaluate to true
|
|
/// </summary>
|
|
Or,
|
|
|
|
/// <summary>
|
|
/// All the conditions in the group should evaluate to false
|
|
/// </summary>
|
|
AndNot,
|
|
|
|
/// <summary>
|
|
/// Any of the conditions in the group should evaluate to false
|
|
/// </summary>
|
|
OrNot
|
|
}
|
|
} |