LotSizingDataModel.Core 2.0.1
Core domain model, shared abstractions and XML-serializable entities.
Loading...
Searching...
No Matches
SalesOption.cs
Go to the documentation of this file.
1using System;
2using System.Linq;
3using System.Xml.Serialization;
5
7
8/// <summary>
9/// Represents optional additional sales beyond mandatory demand.
10/// </summary>
11/// <remarks>
12/// A sales option is intentionally distinct from demand, shortage, backlog and
13/// lost-sales semantics. For each period, up to <see cref="MaximumAdditionalSales"/>
14/// units may be sold at <see cref="UnitPrice"/> per unit.
15/// </remarks>
16[Serializable]
17[XmlType(TypeName = "salesOption")]
18public sealed class SalesOption :
21{
22 private int _itemId;
23 private int _distributionCenterId;
24 private DoubleTimeSeries _maximumAdditionalSales = new();
25 private DoubleTimeSeries _unitPrice = new();
26
27 public SalesOption()
28 {
29 }
30
32 int itemId,
33 int distributionCenterId,
34 int planningHorizon)
35 {
36 if (itemId <= 0)
37 {
38 throw new ArgumentOutOfRangeException(nameof(itemId));
39 }
40
41 if (distributionCenterId <= 0)
42 {
43 throw new ArgumentOutOfRangeException(nameof(distributionCenterId));
44 }
45
46 ItemId = itemId;
47 DistributionCenterId = distributionCenterId;
48 ResizeTimeSeries(planningHorizon);
49 }
50
51 [XmlAttribute("itemId")]
52 public int ItemId
53 {
54 get => _itemId;
55 set
56 {
57 if (value < 0)
58 {
59 throw new ArgumentOutOfRangeException(nameof(value));
60 }
61
62 SetProperty(ref _itemId, value);
63 }
64 }
65
66 [XmlAttribute("distributionCenterId")]
68 {
69 get => _distributionCenterId;
70 set
71 {
72 if (value < 0)
73 {
74 throw new ArgumentOutOfRangeException(nameof(value));
75 }
76
77 SetProperty(ref _distributionCenterId, value);
78 }
79 }
80
81 [XmlElement("maximumAdditionalSales")]
83 {
84 get => _maximumAdditionalSales;
85 set
86 {
87 ArgumentNullException.ThrowIfNull(value);
88 SetProperty(ref _maximumAdditionalSales, value);
89 }
90 }
91
92 [XmlElement("unitPrice")]
94 {
95 get => _unitPrice;
96 set
97 {
98 ArgumentNullException.ThrowIfNull(value);
99 SetProperty(ref _unitPrice, value);
100 }
101 }
102
103 [XmlIgnore]
104 public int PlanningHorizon =>
105 Math.Max(
106 MaximumAdditionalSales.PeriodCount,
107 UnitPrice.PeriodCount);
108
109 [XmlIgnore]
111 MaximumAdditionalSales.PeriodCount == UnitPrice.PeriodCount;
112
113 [XmlIgnore]
114 public bool IsInternallyValid =>
115 ItemId > 0 &&
117 PlanningHorizon > 0 &&
119 MaximumAdditionalSales.All(value => double.IsFinite(value) && value >= 0.0) &&
120 UnitPrice.All(value => double.IsFinite(value) && value >= 0.0);
121
122 public double GetMaximumAdditionalSales(int period) =>
124
125 public void SetMaximumAdditionalSales(int period, double value)
126 {
127 ValidateNonNegative(value, nameof(value));
128 MaximumAdditionalSales[period] = value;
129 }
130
131 public double GetUnitPrice(int period) =>
132 UnitPrice[period];
133
134 public void SetUnitPrice(int period, double value)
135 {
136 ValidateNonNegative(value, nameof(value));
137 UnitPrice[period] = value;
138 }
139
140 public void ResizeTimeSeries(int periodCount)
141 {
142 if (periodCount < 0)
143 {
144 throw new ArgumentOutOfRangeException(nameof(periodCount));
145 }
146
147 MaximumAdditionalSales.Resize(periodCount, 0.0);
148 UnitPrice.Resize(periodCount, 0.0);
149
153 }
154
155 private static void ValidateNonNegative(
156 double value,
157 string parameterName)
158 {
159 if (!double.IsFinite(value) || value < 0.0)
160 {
161 throw new ArgumentOutOfRangeException(
162 parameterName,
163 value,
164 "The value must be finite and non-negative.");
165 }
166 }
167}
Represents a sequence of finite double values indexed by planning period.
Base class for model objects that notify listeners when one of their properties changes.
virtual void OnPropertyChanged([CallerMemberName] string? propertyName=null)
Raises the PropertyChanged event.
SalesOption(int itemId, int distributionCenterId, int planningHorizon)
void SetUnitPrice(int period, double value)
int PlanningHorizon
Gets the number of planning periods currently represented by the object's time-dependent data.
void SetMaximumAdditionalSales(int period, double value)
void ResizeTimeSeries(int periodCount)
Resizes every time-dependent series contained in the object.
Defines a model object containing data indexed by planning period.