Skip to content

Commit 02b4756

Browse files
committed
Improved constants management
1 parent d43c915 commit 02b4756

File tree

9 files changed

+43
-31
lines changed

9 files changed

+43
-31
lines changed

src/app/config/constants.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Application constants and configuration values."""
22

3-
from enum import IntEnum
3+
from enum import Enum, IntEnum
44

55

66
class TimeDefaults(IntEnum):
@@ -12,3 +12,12 @@ class TimeDefaults(IntEnum):
1212
MIN_SIMULATION_TIME = 1800 # min simulation time
1313
MIN_USER_SAMPLING_WINDOW = 1 # 1 second
1414
MAX_USER_SAMPLING_WINDOW = 120 # 2 minutes
15+
16+
17+
class Distribution(str, Enum):
18+
"""Allowed probability distributions for an RVConfig."""
19+
20+
POISSON = "poisson"
21+
NORMAL = "normal"
22+
GAUSSIAN = "gaussian"
23+

src/app/core/event_samplers/gaussian_poisson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def gaussian_poisson_sampling(
5959
mean_req_per_sec_per_user = (
6060
float(
6161
input_data.avg_request_per_minute_per_user.mean)
62-
/ TimeDefaults.MIN_TO_SEC.value
62+
/ TimeDefaults.MIN_TO_SEC
6363
)
6464

6565
now = 0.0 # virtual clock (s)

src/app/core/event_samplers/poisson_poisson.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def poisson_poisson_sampling(
5151
mean_req_per_sec_per_user = (
5252
float(
5353
input_data.avg_request_per_minute_per_user.mean)
54-
/ TimeDefaults.MIN_TO_SEC.value
54+
/ TimeDefaults.MIN_TO_SEC
5555
)
5656

5757
now = 0.0 # virtual clock (s)

src/app/core/simulation/requests_generator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from typing import TYPE_CHECKING
99

10+
from app.config.constants import Distribution
1011
from app.core.event_samplers.gaussian_poisson import gaussian_poisson_sampling
1112
from app.core.event_samplers.poisson_poisson import poisson_poisson_sampling
1213

@@ -36,7 +37,7 @@ def requests_generator(
3637
"""
3738
dist = input_data.avg_active_users.distribution.lower()
3839

39-
if dist in {"gaussian", "normal"}:
40+
if dist in {Distribution.GAUSSIAN, Distribution.NORMAL}:
4041
#Gaussian-Poisson model
4142
return gaussian_poisson_sampling(
4243
input_data=input_data,

src/app/schemas/simulation_input.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
"""Define the schemas for the simulator"""
22

3-
from typing import Literal
43

54
from pydantic import BaseModel, Field, field_validator, model_validator
65

7-
from app.config.constants import TimeDefaults
6+
from app.config.constants import Distribution, TimeDefaults
87

98

109
class RVConfig(BaseModel):
1110
"""class to configure random variables"""
1211

1312
mean: float
14-
distribution: Literal["poisson", "normal", "gaussian"] = "poisson"
13+
distribution: Distribution = Distribution.POISSON
1514
variance: float | None = None
1615

1716
@field_validator("mean", mode="before")
18-
def check_mean_is_number(
17+
def ensure_mean_is_numeric(
1918
cls, # noqa: N805
2019
v: object,
2120
) -> float:
@@ -28,7 +27,10 @@ def check_mean_is_number(
2827
@model_validator(mode="after") # type: ignore[arg-type]
2928
def default_variance(cls, model: "RVConfig") -> "RVConfig": # noqa: N805
3029
"""Set variance = mean when distribution == 'normal' and variance is missing."""
31-
if model.variance is None and model.distribution in {"normal", "gaussian"}:
30+
if model.variance is None and model.distribution in {
31+
Distribution.NORMAL,
32+
Distribution.GAUSSIAN,
33+
}:
3234
model.variance = model.mean
3335
return model
3436

@@ -38,21 +40,21 @@ class SimulationInput(BaseModel):
3840
avg_active_users: RVConfig
3941
avg_request_per_minute_per_user: RVConfig
4042
total_simulation_time: int = Field(
41-
default=TimeDefaults.SIMULATION_TIME.value,
42-
ge=TimeDefaults.MIN_SIMULATION_TIME.value, # minimum simulation time in seconds
43+
default=TimeDefaults.SIMULATION_TIME,
44+
ge=TimeDefaults.MIN_SIMULATION_TIME, # minimum simulation time in seconds
4345
description=(
44-
f"Simulation time in seconds (>= {TimeDefaults.MIN_SIMULATION_TIME.value})."
46+
f"Simulation time in seconds (>= {TimeDefaults.MIN_SIMULATION_TIME})."
4547
),
4648
)
4749

4850
user_sampling_window: int = Field(
49-
default=TimeDefaults.USER_SAMPLING_WINDOW.value,
50-
ge=TimeDefaults.MIN_USER_SAMPLING_WINDOW.value,
51-
le=TimeDefaults.MAX_USER_SAMPLING_WINDOW.value,
51+
default=TimeDefaults.USER_SAMPLING_WINDOW,
52+
ge=TimeDefaults.MIN_USER_SAMPLING_WINDOW,
53+
le=TimeDefaults.MAX_USER_SAMPLING_WINDOW,
5254
description=(
5355
"Sampling window in seconds "
54-
f"({TimeDefaults.MIN_USER_SAMPLING_WINDOW.value}-"
55-
f"{TimeDefaults.MAX_USER_SAMPLING_WINDOW.value})."
56+
f"({TimeDefaults.MIN_USER_SAMPLING_WINDOW}-"
57+
f"{TimeDefaults.MAX_USER_SAMPLING_WINDOW})."
5658
),
5759
)
5860

tests/unit/sampler/test_gaussian_poisson.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ def base_input() -> SimulationInput:
2525
mean=10.0, variance=4.0, distribution="gaussian",
2626
),
2727
avg_request_per_minute_per_user=RVConfig(mean=30.0),
28-
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME.value,
29-
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW.value,
28+
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME,
29+
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW,
3030
)
3131

3232

tests/unit/sampler/test_poisson_posson.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ def base_input() -> SimulationInput:
2222
avg_active_users={"mean": 1.0, "distribution": "poisson"},
2323
# … sending on average 60 req/min → 1 req/s
2424
avg_request_per_minute_per_user={"mean": 60.0, "distribution": "poisson"},
25-
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME.value, # 30 min
26-
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW.value, # 60 s
25+
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME, # 30 min
26+
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW, # 60 s
2727
)
2828

2929

@@ -94,8 +94,8 @@ def test_zero_users_produces_no_events(base_input: SimulationInput) -> None:
9494
input_data = SimulationInput(
9595
avg_active_users=RVConfig(mean=0.0, distribution="poisson"),
9696
avg_request_per_minute_per_user=RVConfig(mean=60.0, distribution="poisson"),
97-
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME.value,
98-
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW.value,
97+
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME,
98+
user_sampling_window=TimeDefaults.USER_SAMPLING_WINDOW,
9999
)
100100

101101
rng = np.random.default_rng(123)

tests/unit/simulation/test_events_generator_input.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def test_default_user_sampling_window() -> None:
8888
avg_active_users={"mean": 1.0, "distribution": "poisson"},
8989
avg_request_per_minute_per_user={"mean": 1.0, "distribution": "poisson"},
9090
)
91-
assert inp.user_sampling_window == TimeDefaults.USER_SAMPLING_WINDOW.value
91+
assert inp.user_sampling_window == TimeDefaults.USER_SAMPLING_WINDOW
9292

9393

9494
def test_explicit_user_sampling_window_kept() -> None:
@@ -125,7 +125,7 @@ def test_user_sampling_window_above_max_raises() -> None:
125125
Passing user_sampling_window > MAX_USER_SAMPLING_WINDOW
126126
must raise a ValidationError.
127127
"""
128-
too_large = TimeDefaults.MAX_USER_SAMPLING_WINDOW.value + 1
128+
too_large = TimeDefaults.MAX_USER_SAMPLING_WINDOW + 1
129129
with pytest.raises(ValidationError) as excinfo:
130130
SimulationInput(
131131
avg_active_users={"mean": 1.0, "distribution": "poisson"},
@@ -137,7 +137,7 @@ def test_user_sampling_window_above_max_raises() -> None:
137137
assert any(err["loc"] == ("user_sampling_window",) for err in errors)
138138

139139
expected_snippet = (
140-
f"less than or equal to {TimeDefaults.MAX_USER_SAMPLING_WINDOW.value}"
140+
f"less than or equal to {TimeDefaults.MAX_USER_SAMPLING_WINDOW}"
141141
)
142142
assert any(expected_snippet in err["msg"] for err in errors)
143143

@@ -153,7 +153,7 @@ def test_default_total_simulation_time() -> None:
153153
avg_active_users={"mean": 1.0, "distribution": "poisson"},
154154
avg_request_per_minute_per_user={"mean": 1.0, "distribution": "poisson"},
155155
)
156-
assert inp.total_simulation_time == TimeDefaults.SIMULATION_TIME.value
156+
assert inp.total_simulation_time == TimeDefaults.SIMULATION_TIME
157157

158158

159159
def test_explicit_total_simulation_time_kept() -> None:
@@ -190,7 +190,7 @@ def test_total_simulation_time_below_minimum_raises() -> None:
190190
Passing total_simulation_time < MIN_SIMULATION_TIME
191191
must raise a ValidationError.
192192
"""
193-
too_small = TimeDefaults.MIN_SIMULATION_TIME.value - 1
193+
too_small = TimeDefaults.MIN_SIMULATION_TIME - 1
194194
with pytest.raises(ValidationError) as excinfo:
195195
SimulationInput(
196196
avg_active_users={"mean": 1.0, "distribution": "poisson"},
@@ -203,7 +203,7 @@ def test_total_simulation_time_below_minimum_raises() -> None:
203203
assert any(err["loc"] == ("total_simulation_time",) for err in errors)
204204

205205
expected_snippet = (
206-
f"greater than or equal to {TimeDefaults.MIN_SIMULATION_TIME.value}"
206+
f"greater than or equal to {TimeDefaults.MIN_SIMULATION_TIME}"
207207
)
208208
assert any(expected_snippet in err["msg"] for err in errors)
209209

tests/unit/simulation/test_requests_generator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def base_input() -> SimulationInput:
2929
return SimulationInput(
3030
avg_active_users={"mean": 1.0},
3131
avg_request_per_minute_per_user={"mean": 2.0},
32-
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME.value,
32+
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME,
3333
)
3434

3535
# --------------------------------------------------------------
@@ -74,7 +74,7 @@ def test_requests_generator_dispatches_to_correct_sampler(
7474
input_data = SimulationInput(
7575
avg_active_users={"mean": 1.0, "distribution": dist},
7676
avg_request_per_minute_per_user={"mean": 1.0},
77-
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME.value,
77+
total_simulation_time=TimeDefaults.MIN_SIMULATION_TIME,
7878
)
7979
rng = np.random.default_rng(0)
8080
gen = requests_generator(input_data, rng=rng)

0 commit comments

Comments
 (0)