1#ifndef DASMIG_EXT_STATS_OBSERVER_HPP
2#define DASMIG_EXT_STATS_OBSERVER_HPP
4#include "../entitygen.hpp"
27 using clock = std::chrono::steady_clock;
28 using duration = std::chrono::steady_clock::duration;
69 std::numeric_limits<std::size_t>::max()};
80 std::map<std::wstring,
103 return duration::zero();
104 return it->second / ct->second;
119 std::size_t total{0};
121 return static_cast<double>(total)
139 [[nodiscard]] std::wstring
report()
const
141 std::wostringstream o;
142 o << std::fixed << std::setprecision(2);
145 return std::chrono::duration_cast<
146 std::chrono::microseconds>(d).count();
150 o << L
"=== Entity Summary ===\n"
161 o << L
"\n=== Entity Timing ===\n"
172 o << L
"\n=== Components per Entity ===\n";
182 o << L
" (no entities generated)\n";
186 o << L
"\n=== Component Summary ===\n"
199 std::map<std::wstring, int> all_keys;
205 if (!all_keys.empty())
207 o << L
"\n=== Per-Component Breakdown ===\n";
209 for (
const auto& [key, _] : all_keys)
211 o << L
"\n [" << key << L
"]\n";
213 auto count_or = [](
const auto& m,
const std::wstring& k)
216 return it != m.end() ? it->second : 0;
224 o << L
" Generated : " << gen_n << L
'\n'
225 << L
" Skipped : " << skip_n << L
'\n'
226 << L
" Retries : " << ret_n << L
'\n'
227 << L
" Failures : " << fail_n << L
'\n';
232 o << L
" Time total: " << us(it->second) << L
" us\n"
240 o << L
" Time min : " << us(it->second) << L
" us\n";
246 o << L
" Time max : " << us(it->second) << L
" us\n";
254 o << L
"\n=== Value Distribution ===\n";
258 o << L
"\n [" << key << L
"] ("
259 << dist.size() << L
" distinct values)\n";
262 std::vector<std::pair<std::wstring, std::size_t>> sorted(
263 dist.begin(), dist.end());
264 std::ranges::sort(sorted, [](
const auto& a,
const auto& b) {
265 return a.second > b.second;
268 auto total_n = count_for(key);
269 for (
const auto& [val, n] : sorted)
271 double pct = total_n > 0
272 ?
static_cast<double>(n)
273 /
static_cast<double>(total_n) * 100.0
275 o << L
" " << val << L
" : " << n
276 << L
" (" << pct << L
" %)\n";
325 _entity_start = clock::now();
326 _current_entity_components = 0;
333 auto elapsed = clock::now() - _entity_start;
347 _component_start[key] = clock::now();
351 const std::any& value)
override
355 ++_current_entity_components;
357 auto it = _component_start.find(key);
358 if (it != _component_start.end())
360 auto elapsed = clock::now() - it->second;
372 if (elapsed < mn) mn = elapsed;
373 if (elapsed > mx) mx = elapsed;
385 void on_skip(
const std::wstring& key)
override
393 const std::any& )
override
416 clock::time_point _entity_start{};
417 std::map<std::wstring, clock::time_point> _component_start;
418 std::size_t _current_entity_components{0};
421 static std::wstring display_for(
const std::any& value)
423 if (
auto* ws = std::any_cast<std::wstring>(&value))
425 if (
auto* i = std::any_cast<int>(&value))
426 return std::to_wstring(*i);
427 if (
auto* d = std::any_cast<double>(&value))
428 return std::to_wstring(*d);
429 if (
auto* f = std::any_cast<float>(&value))
430 return std::to_wstring(*f);
431 if (
auto* l = std::any_cast<long>(&value))
432 return std::to_wstring(*l);
433 if (
auto* b = std::any_cast<bool>(&value))
434 return *b ? L
"true" : L
"false";
439 [[nodiscard]] std::size_t count_for(
const std::wstring& key)
const
450 return os << stats.
report();
A generated entity holding component values in registration order.
Observer that collects comprehensive generation statistics.
std::map< std::wstring, std::size_t > component_retries
Total retries per key.
std::map< std::wstring, std::size_t > component_counts
Successful generations per key.
void on_skip(const std::wstring &key) override
Called when a component is skipped (weight roll or conditional exclusion).
double component_retry_rate() const
Retry rate: total retries / total component generations.
std::map< std::wstring, std::size_t > component_skip_counts
Skips per key.
std::size_t entities_generated
Total entities successfully generated.
std::chrono::steady_clock clock
Clock type used for timing.
std::chrono::steady_clock::duration duration
Duration type.
duration min_entity_time
Fastest entity generation.
void on_after_entity_retry(std::size_t) override
Called after an entity validation retry.
std::map< std::wstring, std::map< std::wstring, std::size_t > > value_distribution
Per-component key, counts how many times each display string appeared.
std::map< std::wstring, std::size_t > component_failure_counts
Failures per key.
std::size_t entity_retries
Total entity-level validation retries.
void reset()
Zero all counters, timers, and distributions.
std::map< std::wstring, duration > component_max_times
Slowest per key.
duration avg_component_time(const std::wstring &key) const
Average generation time per component key.
void on_before_component(const std::wstring &key) override
Called before a component is generated.
void on_entity_fail() override
Called when entity validation is exhausted (precedes exception).
std::size_t total_components_in_entities
Sum for computing the average.
double entity_retry_rate() const
Entity retry rate: entity retries / entities generated.
std::size_t min_components_per_entity
Fewest components in any entity.
void on_after_retry(const std::wstring &key, std::size_t, const std::any &) override
Called after a component validation retry.
std::size_t max_components_per_entity
Most components in any entity.
std::wstring report() const
Produce a human-readable wide-string report of all collected stats.
duration max_entity_time
Slowest entity generation.
duration total_generation_time
Wall-clock time summed across all entities.
std::size_t entity_failures
Total entity-level validation failures.
std::size_t components_skipped
Total components skipped (weight or conditional).
void on_component_fail(const std::wstring &key) override
Called when component validation is exhausted (precedes exception).
void on_after_generate(const entity &) override
Called after an entity is successfully generated.
double avg_components_per_entity() const
Average components produced per entity (0.0 if none generated).
duration avg_entity_time() const
Average generation time per entity (zero if none generated).
std::size_t components_generated
Total components successfully generated.
std::map< std::wstring, duration > component_times
Total generation time per key.
void on_before_generate() override
Called before an entity is generated.
std::size_t component_failures
Total component validation failures.
void on_after_component(const std::wstring &key, const std::any &value) override
Called after a component is successfully generated.
std::map< std::wstring, duration > component_min_times
Fastest per key.
Observer interface for hooking into generation lifecycle events.
std::wostream & operator<<(std::wostream &os, const stats_observer &stats)
Stream operator for one-liner report output.