Merge pull request #1 from StewKI/feature-shape

Shape domain
This commit is contained in:
Andrija Stevanović
2026-02-08 21:59:36 +01:00
committed by GitHub
15 changed files with 321 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
using AipsCore.Domain.Abstract.Rule;
namespace AipsCore.Domain.Common.Validation.Rules;
public class ColorFormatRule : AbstractRule
{
private readonly string _colorValue;
protected override string ErrorCode => "color_format";
protected override string ErrorMessage => "Color should be in format '#000000'";
public ColorFormatRule(string colorValue)
{
_colorValue = colorValue;
}
public override bool Validate()
{
if (_colorValue.Length != 7) return false;
if (_colorValue[0] != '#') return false;
for (int i = 1; i < _colorValue.Length; i++)
{
if (!char.IsAsciiHexDigit(_colorValue[i])) return false;
}
return true;
}
}

View File

@@ -0,0 +1,23 @@
using System.Numerics;
using AipsCore.Domain.Abstract.Rule;
namespace AipsCore.Domain.Common.Validation.Rules;
public class MaxValueRule<T> : AbstractRule where T : INumber<T>
{
private readonly T _value;
private readonly T _maximum;
public MaxValueRule(T value, T maximum)
{
_value = value;
_maximum = maximum;
}
protected override string ErrorCode => "max_value";
protected override string ErrorMessage => $"Value of '{ValueObjectName}' should be at most {_maximum}";
public override bool Validate()
{
return _value <= _maximum;
}
}

View File

@@ -0,0 +1,23 @@
using System.Numerics;
using AipsCore.Domain.Abstract.Rule;
namespace AipsCore.Domain.Common.Validation.Rules;
public class MinValueRule<T>: AbstractRule where T : INumber<T>
{
private readonly T _value;
private readonly T _minimum;
public MinValueRule(T value, T minimum)
{
_value = value;
_minimum = minimum;
}
protected override string ErrorCode => "min_value";
protected override string ErrorMessage => $"Value of '{ValueObjectName}' should be at least {_minimum}";
public override bool Validate()
{
return _value >= _minimum;
}
}

View File

@@ -0,0 +1,23 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
using AipsCore.Domain.Common.Validation.Rules;
namespace AipsCore.Domain.Common.ValueObjects;
public record Color : AbstractValueObject
{
public string Value { get; }
public Color(string value)
{
Value = value;
}
protected override ICollection<IRule> GetValidationRules()
{
return
[
new ColorFormatRule(Value)
];
}
}

View File

@@ -0,0 +1,9 @@
namespace AipsCore.Domain.Models.Shape.Enums;
public enum ShapeType
{
Rectangle,
Line,
Arrow,
Text
}

View File

@@ -0,0 +1,27 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.Shape.Enums;
using AipsCore.Domain.Models.Shape.ValueObjects;
using AipsCore.Domain.Models.Whiteboard.ValueObjects;
namespace AipsCore.Domain.Models.Shape;
public abstract class Shape
{
public ShapeId Id { get; }
public WhiteboardId WhiteboardId { get; private set; }
public abstract ShapeType ShapeType { get; }
public Position Position { get; private set; }
public Color Color { get; private set; }
protected Shape(ShapeId id, WhiteboardId whiteboardId, Position position, Color color)
{
Id = id;
Position = position;
Color = color;
WhiteboardId = whiteboardId;
}
}

View File

@@ -0,0 +1,20 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.Shape.Enums;
using AipsCore.Domain.Models.Shape.ValueObjects;
using AipsCore.Domain.Models.Whiteboard.ValueObjects;
namespace AipsCore.Domain.Models.Shape.Sub.Arrow;
public class Arrow : Shape
{
public Position EndPosition { get; private set; }
public Thickness Thickness { get; private set; }
public Arrow(ShapeId id, WhiteboardId whiteboardId, Position position, Color color, Position endPosition, Thickness thickness) : base(id, whiteboardId, position, color)
{
EndPosition = endPosition;
Thickness = thickness;
}
public override ShapeType ShapeType => ShapeType.Arrow;
}

View File

@@ -0,0 +1,20 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.Shape.Enums;
using AipsCore.Domain.Models.Shape.ValueObjects;
using AipsCore.Domain.Models.Whiteboard.ValueObjects;
namespace AipsCore.Domain.Models.Shape.Sub.Line;
public class Line : Shape
{
public Position EndPosition { get; private set; }
public Thickness Thickness { get; private set; }
public Line(ShapeId id, WhiteboardId whiteboardId, Position position, Color color, Position endPosition, Thickness thickness) : base(id, whiteboardId, position, color)
{
EndPosition = endPosition;
Thickness = thickness;
}
public override ShapeType ShapeType => ShapeType.Line;
}

View File

@@ -0,0 +1,23 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.Shape.Enums;
using AipsCore.Domain.Models.Shape.ValueObjects;
using AipsCore.Domain.Models.Whiteboard.ValueObjects;
namespace AipsCore.Domain.Models.Shape.Sub.Rectangle;
public class Rectangle : Shape
{
public override ShapeType ShapeType => ShapeType.Rectangle;
public Position EndPosition { get; }
public Thickness BorderThickness { get; }
public Rectangle(ShapeId id, WhiteboardId whiteboardId, Position position, Color color, Position endPosition, Thickness borderThickness)
: base(id, whiteboardId, position, color)
{
EndPosition = endPosition;
BorderThickness = borderThickness;
}
}

View File

@@ -0,0 +1,23 @@
using AipsCore.Domain.Common.ValueObjects;
using AipsCore.Domain.Models.Shape.Enums;
using AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects;
using AipsCore.Domain.Models.Shape.ValueObjects;
using AipsCore.Domain.Models.Whiteboard.ValueObjects;
namespace AipsCore.Domain.Models.Shape.Sub.TextShape;
public class TextShape : Shape
{
public TextShapeValue TextShapeValue { get; private set; }
public TextShapeSize TextShapeSize { get; private set; }
public TextShape(ShapeId id, WhiteboardId whiteboardId, Position position, Color color, TextShapeValue textShapeValue, TextShapeSize textShapeSize)
: base(id, whiteboardId, position, color)
{
TextShapeValue = textShapeValue;
TextShapeSize = textShapeSize;
}
public override ShapeType ShapeType => ShapeType.Text;
}

View File

@@ -0,0 +1,27 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
using AipsCore.Domain.Common.Validation.Rules;
namespace AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects;
public record TextShapeSize : AbstractValueObject
{
public const int MaxTextShapeSize = 72;
public const int MinTextShapeSize = 8;
public int Size { get; }
public TextShapeSize(int size)
{
Size = size;
}
protected override ICollection<IRule> GetValidationRules()
{
return
[
new MaxValueRule<int>(Size, MaxTextShapeSize),
new MinValueRule<int>(Size, MinTextShapeSize)
];
}
}

View File

@@ -0,0 +1,19 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
namespace AipsCore.Domain.Models.Shape.Sub.TextShape.ValueObjects;
public record TextShapeValue: AbstractValueObject
{
public string Text { get; }
public TextShapeValue(string text)
{
Text = text;
}
protected override ICollection<IRule> GetValidationRules()
{
return [];
}
}

View File

@@ -0,0 +1,23 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
namespace AipsCore.Domain.Models.Shape.ValueObjects;
public record Position : AbstractValueObject
{
public int X { get; }
public int Y { get; }
public Position(int x, int y)
{
X = x;
Y = y;
}
protected override ICollection<IRule> GetValidationRules()
{
return [
];
}
};

View File

@@ -0,0 +1,5 @@
using AipsCore.Domain.Common.ValueObjects;
namespace AipsCore.Domain.Models.Shape.ValueObjects;
public record ShapeId(string Value) : DomainId(Value);

View File

@@ -0,0 +1,27 @@
using AipsCore.Domain.Abstract.Rule;
using AipsCore.Domain.Abstract.ValueObject;
using AipsCore.Domain.Common.Validation.Rules;
namespace AipsCore.Domain.Models.Shape.ValueObjects;
public record Thickness : AbstractValueObject
{
private const int MaxThickness = 8;
private const int MinThickness = 1;
private readonly int _value;
public Thickness(int value)
{
_value = value;
}
protected override ICollection<IRule> GetValidationRules()
{
return
[
new MinValueRule<int>(_value, MinThickness),
new MaxValueRule<int>(_value, MaxThickness),
];
}
}