yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
canvas_usage_tracker.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <sstream>
5#include <iomanip>
6#include <chrono>
7
8#include "util/log.h"
9
10namespace yaze {
11namespace gui {
12namespace canvas {
13
14void CanvasUsageTracker::Initialize(const std::string& canvas_id) {
15 canvas_id_ = canvas_id;
17 current_stats_.session_start = std::chrono::steady_clock::now();
20}
21
23 if (current_stats_.usage_mode != usage) {
24 // Save current stats before changing mode
26
27 // Update usage mode
30
31 // Record mode change interaction
33
34 LOG_DEBUG("CanvasUsage", "Canvas %s: Usage mode changed to %s",
35 canvas_id_.c_str(), GetUsageModeName(usage).c_str());
36 }
37}
38
40 const std::string& details) {
41 interaction_history_.push_back({interaction, details});
42
43 // Update activity time
44 last_activity_ = std::chrono::steady_clock::now();
45
46 // Update interaction counts
47 switch (interaction) {
50 break;
53 break;
56 break;
59 break;
62 break;
65 break;
66 default:
67 break;
68 }
69}
70
71void CanvasUsageTracker::RecordOperation(const std::string& operation_name,
72 double time_ms) {
73 operation_times_[operation_name].push_back(time_ms);
75
76 // Update average operation time
77 double total_time = 0.0;
78 int total_ops = 0;
79 for (const auto& [name, times] : operation_times_) {
80 for (double t : times) {
81 total_time += t;
82 total_ops++;
83 }
84 }
85
86 if (total_ops > 0) {
87 current_stats_.average_operation_time_ms = total_time / total_ops;
88 }
89
90 // Update max operation time
93 }
94
95 // Record as interaction
97}
98
99void CanvasUsageTracker::UpdateCanvasState(const ImVec2& canvas_size,
100 const ImVec2& content_size,
101 float global_scale,
102 float grid_step,
103 bool enable_grid,
104 bool enable_hex_labels,
105 bool enable_custom_labels) {
106 current_stats_.canvas_size = canvas_size;
107 current_stats_.content_size = content_size;
108 current_stats_.global_scale = global_scale;
109 current_stats_.grid_step = grid_step;
110 current_stats_.enable_grid = enable_grid;
111 current_stats_.enable_hex_labels = enable_hex_labels;
112 current_stats_.enable_custom_labels = enable_custom_labels;
113
114 // Update activity time
115 last_activity_ = std::chrono::steady_clock::now();
116}
117
118// These methods are already defined in the header as inline, removing duplicates
119
121 switch (usage) {
122 case CanvasUsage::kTilePainting: return "Tile Painting";
123 case CanvasUsage::kTileSelecting: return "Tile Selecting";
124 case CanvasUsage::kSelectRectangle: return "Rectangle Selection";
125 case CanvasUsage::kColorPainting: return "Color Painting";
126 case CanvasUsage::kBitmapEditing: return "Bitmap Editing";
127 case CanvasUsage::kPaletteEditing: return "Palette Editing";
128 case CanvasUsage::kBppConversion: return "BPP Conversion";
129 case CanvasUsage::kPerformanceMode: return "Performance Mode";
130 case CanvasUsage::kUnknown: return "Unknown";
131 default: return "Unknown";
132 }
133}
134
136 switch (usage) {
137 case CanvasUsage::kTilePainting: return ImVec4(0.2F, 1.0F, 0.2F, 1.0F); // Green
138 case CanvasUsage::kTileSelecting: return ImVec4(0.2F, 0.8F, 1.0F, 1.0F); // Blue
139 case CanvasUsage::kSelectRectangle: return ImVec4(1.0F, 0.8F, 0.2F, 1.0F); // Yellow
140 case CanvasUsage::kColorPainting: return ImVec4(1.0F, 0.2F, 1.0F, 1.0F); // Magenta
141 case CanvasUsage::kBitmapEditing: return ImVec4(1.0F, 0.5F, 0.2F, 1.0F); // Orange
142 case CanvasUsage::kPaletteEditing: return ImVec4(0.8F, 0.2F, 1.0F, 1.0F); // Purple
143 case CanvasUsage::kBppConversion: return ImVec4(0.2F, 1.0F, 1.0F, 1.0F); // Cyan
144 case CanvasUsage::kPerformanceMode: return ImVec4(1.0F, 0.2F, 0.2F, 1.0F); // Red
145 case CanvasUsage::kUnknown: return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
146 default: return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
147 }
148}
149
150std::vector<std::string> CanvasUsageTracker::GetUsageRecommendations() const {
151 std::vector<std::string> recommendations;
152
153 // Analyze usage patterns and provide recommendations
154 if (current_stats_.mouse_clicks > 100) {
155 recommendations.push_back("Consider using keyboard shortcuts to reduce mouse usage");
156 }
157
159 recommendations.push_back("Frequent context menu usage - consider adding toolbar buttons");
160 }
161
162 if (current_stats_.modal_opens > 10) {
163 recommendations.push_back("Many modal dialogs opened - consider persistent panels");
164 }
165
167 recommendations.push_back("Operations are slow - check performance optimization");
168 }
169
171 recommendations.push_back("Frequent mode switching - consider mode-specific toolbars");
172 }
173
174 return recommendations;
175}
176
178 std::ostringstream report;
179
180 report << "Canvas Usage Report for: " << canvas_id_ << "\n";
181 report << "==========================================\n\n";
182
183 // Session information
184 auto now = std::chrono::steady_clock::now();
185 auto session_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
186 now - session_start_);
187
188 report << "Session Information:\n";
189 report << " Duration: " << FormatDuration(session_duration) << "\n";
190 report << " Current Mode: " << GetUsageModeName(current_stats_.usage_mode) << "\n";
191 report << " Mode Changes: " << current_stats_.mode_changes << "\n\n";
192
193 // Interaction statistics
194 report << "Interaction Statistics:\n";
195 report << " Mouse Clicks: " << current_stats_.mouse_clicks << "\n";
196 report << " Mouse Drags: " << current_stats_.mouse_drags << "\n";
197 report << " Context Menu Opens: " << current_stats_.context_menu_opens << "\n";
198 report << " Modal Opens: " << current_stats_.modal_opens << "\n";
199 report << " Tool Changes: " << current_stats_.tool_changes << "\n\n";
200
201 // Performance statistics
202 report << "Performance Statistics:\n";
203 report << " Total Operations: " << current_stats_.total_operations << "\n";
204 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
206 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
208
209 // Canvas state
210 report << "Canvas State:\n";
211 report << " Canvas Size: " << static_cast<int>(current_stats_.canvas_size.x)
212 << " x " << static_cast<int>(current_stats_.canvas_size.y) << "\n";
213 report << " Content Size: " << static_cast<int>(current_stats_.content_size.x)
214 << " x " << static_cast<int>(current_stats_.content_size.y) << "\n";
215 report << " Global Scale: " << std::fixed << std::setprecision(2)
216 << current_stats_.global_scale << "\n";
217 report << " Grid Step: " << std::fixed << std::setprecision(1)
218 << current_stats_.grid_step << "\n";
219 report << " Grid Enabled: " << (current_stats_.enable_grid ? "Yes" : "No") << "\n";
220 report << " Hex Labels: " << (current_stats_.enable_hex_labels ? "Yes" : "No") << "\n";
221 report << " Custom Labels: " << (current_stats_.enable_custom_labels ? "Yes" : "No") << "\n\n";
222
223 // Operation breakdown
224 if (!operation_times_.empty()) {
225 report << "Operation Breakdown:\n";
226 for (const auto& [operation, times] : operation_times_) {
227 double avg_time = CalculateAverageOperationTime(operation);
228 report << " " << operation << ": " << times.size() << " operations, "
229 << "avg " << std::fixed << std::setprecision(2) << avg_time << " ms\n";
230 }
231 report << "\n";
232 }
233
234 // Recommendations
235 auto recommendations = GetUsageRecommendations();
236 if (!recommendations.empty()) {
237 report << "Recommendations:\n";
238 for (const auto& rec : recommendations) {
239 report << " • " << rec << "\n";
240 }
241 }
242
243 return report.str();
244}
245
255
261
263 // Update final statistics
266
267 // Save final stats
269
270 LOG_DEBUG("CanvasUsage", "Canvas %s: Session ended. Duration: %s, Operations: %d",
271 canvas_id_.c_str(),
272 FormatDuration(std::chrono::duration_cast<std::chrono::milliseconds>(
273 std::chrono::steady_clock::now() - session_start_)).c_str(),
275}
276
278 auto now = std::chrono::steady_clock::now();
279 auto time_since_activity = std::chrono::duration_cast<std::chrono::milliseconds>(
280 now - last_activity_);
281
282 if (time_since_activity.count() < 5000) { // 5 seconds threshold
283 current_stats_.active_time += time_since_activity;
284 }
285}
286
288 auto now = std::chrono::steady_clock::now();
289 auto time_since_activity = std::chrono::duration_cast<std::chrono::milliseconds>(
290 now - last_activity_);
291
292 if (time_since_activity.count() >= 5000) { // 5 seconds threshold
293 current_stats_.idle_time += time_since_activity;
294 }
295}
296
298 // Update final times
301
302 // Calculate total time
304
305 // Save to history
307
308 // Reset for next session
310 current_stats_.session_start = std::chrono::steady_clock::now();
311}
312
313double CanvasUsageTracker::CalculateAverageOperationTime(const std::string& operation_name) const {
314 auto it = operation_times_.find(operation_name);
315 if (it == operation_times_.end() || it->second.empty()) {
316 return 0.0;
317 }
318
319 double total = 0.0;
320 for (double time : it->second) {
321 total += time;
322 }
323
324 return total / it->second.size();
325}
326
327std::string CanvasUsageTracker::FormatDuration(const std::chrono::milliseconds& duration) const {
328 auto total_ms = duration.count();
329 auto hours = total_ms / 3600000;
330 auto minutes = (total_ms % 3600000) / 60000;
331 auto seconds = (total_ms % 60000) / 1000;
332
333 std::ostringstream ss;
334 if (hours > 0) {
335 ss << hours << "h " << minutes << "m " << seconds << "s";
336 } else if (minutes > 0) {
337 ss << minutes << "m " << seconds << "s";
338 } else {
339 ss << seconds << "s";
340 }
341
342 return ss.str();
343}
344
345// CanvasUsageManager implementation
346
348 static CanvasUsageManager instance;
349 return instance;
350}
351
352void CanvasUsageManager::RegisterTracker(const std::string& canvas_id,
353 std::shared_ptr<CanvasUsageTracker> tracker) {
354 trackers_[canvas_id] = tracker;
355 LOG_DEBUG("CanvasUsage", "Registered usage tracker for canvas: %s", canvas_id.c_str());
356}
357
358std::shared_ptr<CanvasUsageTracker> CanvasUsageManager::GetTracker(const std::string& canvas_id) {
359 auto it = trackers_.find(canvas_id);
360 if (it != trackers_.end()) {
361 return it->second;
362 }
363 return nullptr;
364}
365
367 CanvasUsageStats global_stats;
368
369 for (const auto& [id, tracker] : trackers_) {
370 const auto& stats = tracker->GetCurrentStats();
371
372 global_stats.mouse_clicks += stats.mouse_clicks;
373 global_stats.mouse_drags += stats.mouse_drags;
374 global_stats.context_menu_opens += stats.context_menu_opens;
375 global_stats.modal_opens += stats.modal_opens;
376 global_stats.tool_changes += stats.tool_changes;
377 global_stats.mode_changes += stats.mode_changes;
378 global_stats.total_operations += stats.total_operations;
379
380 // Update averages
381 if (stats.average_operation_time_ms > global_stats.average_operation_time_ms) {
382 global_stats.average_operation_time_ms = stats.average_operation_time_ms;
383 }
384 if (stats.max_operation_time_ms > global_stats.max_operation_time_ms) {
385 global_stats.max_operation_time_ms = stats.max_operation_time_ms;
386 }
387 }
388
389 return global_stats;
390}
391
393 std::ostringstream report;
394
395 report << "Global Canvas Usage Report\n";
396 report << "==========================\n\n";
397
398 report << "Registered Canvases: " << trackers_.size() << "\n\n";
399
400 for (const auto& [id, tracker] : trackers_) {
401 report << "Canvas: " << id << "\n";
402 report << "----------------------------------------\n";
403 report << tracker->ExportUsageReport() << "\n\n";
404 }
405
406 // Global summary
407 auto global_stats = GetGlobalStats();
408 report << "Global Summary:\n";
409 report << " Total Mouse Clicks: " << global_stats.mouse_clicks << "\n";
410 report << " Total Operations: " << global_stats.total_operations << "\n";
411 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
412 << global_stats.average_operation_time_ms << " ms\n";
413 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
414 << global_stats.max_operation_time_ms << " ms\n";
415
416 return report.str();
417}
418
420 for (auto& [id, tracker] : trackers_) {
421 tracker->ClearHistory();
422 }
423 trackers_.clear();
424 LOG_DEBUG("CanvasUsage", "Cleared all canvas usage trackers");
425}
426
427} // namespace canvas
428} // namespace gui
429} // namespace yaze
Global canvas usage tracker manager.
std::unordered_map< std::string, std::shared_ptr< CanvasUsageTracker > > trackers_
void RegisterTracker(const std::string &canvas_id, std::shared_ptr< CanvasUsageTracker > tracker)
Register a canvas tracker.
std::string ExportGlobalReport() const
Export global usage report.
CanvasUsageStats GetGlobalStats() const
Get global usage statistics.
std::shared_ptr< CanvasUsageTracker > GetTracker(const std::string &canvas_id)
Get tracker for canvas.
std::chrono::steady_clock::time_point session_start_
std::vector< CanvasUsageStats > usage_history_
std::vector< std::string > GetUsageRecommendations() const
Get usage recommendations.
std::unordered_map< std::string, std::vector< double > > operation_times_
std::chrono::steady_clock::time_point last_activity_
std::string FormatDuration(const std::chrono::milliseconds &duration) const
std::vector< std::pair< CanvasInteraction, std::string > > interaction_history_
void RecordInteraction(CanvasInteraction interaction, const std::string &details="")
Record an interaction.
double CalculateAverageOperationTime(const std::string &operation_name) const
void SetUsageMode(CanvasUsage usage)
Set the current usage mode.
std::string ExportUsageReport() const
Export usage report.
std::string GetUsageModeName(CanvasUsage usage) const
Get usage mode name.
void Initialize(const std::string &canvas_id)
Initialize the usage tracker.
void UpdateCanvasState(const ImVec2 &canvas_size, const ImVec2 &content_size, float global_scale, float grid_step, bool enable_grid, bool enable_hex_labels, bool enable_custom_labels)
Update canvas state.
void RecordOperation(const std::string &operation_name, double time_ms)
Record operation timing.
ImVec4 GetUsageModeColor(CanvasUsage usage) const
Get usage mode color for UI.
#define LOG_DEBUG(category, format,...)
Definition log.h:104
CanvasUsage
Canvas usage patterns and tracking.
CanvasInteraction
Canvas interaction types.
Main namespace for the application.
std::chrono::steady_clock::time_point session_start