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 <chrono>
5#include <iomanip>
6#include <sstream>
7
8#include "util/log.h"
9
10namespace yaze {
11namespace gui {
12
13void CanvasUsageTracker::Initialize(const std::string& canvas_id) {
14 canvas_id_ = canvas_id;
16 current_stats_.session_start = std::chrono::steady_clock::now();
19}
20
22 if (current_stats_.usage_mode != usage) {
23 // Save current stats before changing mode
25
26 // Update usage mode
29
30 // Record mode change interaction
32
33 LOG_DEBUG("CanvasUsage", "Canvas %s: Usage mode changed to %s",
34 canvas_id_.c_str(), GetUsageModeName(usage).c_str());
35 }
36}
37
39 const std::string& details) {
40 interaction_history_.push_back({interaction, details});
41
42 // Update activity time
43 last_activity_ = std::chrono::steady_clock::now();
44
45 // Update interaction counts
46 switch (interaction) {
49 break;
52 break;
55 break;
58 break;
61 break;
64 break;
65 default:
66 break;
67 }
68}
69
70void CanvasUsageTracker::RecordOperation(const std::string& operation_name,
71 double time_ms) {
72 operation_times_[operation_name].push_back(time_ms);
74
75 // Update average operation time
76 double total_time = 0.0;
77 int total_ops = 0;
78 for (const auto& [name, times] : operation_times_) {
79 for (double t : times) {
80 total_time += t;
81 total_ops++;
82 }
83 }
84
85 if (total_ops > 0) {
86 current_stats_.average_operation_time_ms = total_time / total_ops;
87 }
88
89 // Update max operation time
92 }
93
94 // Record as interaction
96}
97
98void CanvasUsageTracker::UpdateCanvasState(const ImVec2& canvas_size,
99 const ImVec2& content_size,
100 float global_scale, float grid_step,
101 bool enable_grid,
102 bool enable_hex_labels,
103 bool enable_custom_labels) {
104 current_stats_.canvas_size = canvas_size;
105 current_stats_.content_size = content_size;
106 current_stats_.global_scale = global_scale;
107 current_stats_.grid_step = grid_step;
108 current_stats_.enable_grid = enable_grid;
109 current_stats_.enable_hex_labels = enable_hex_labels;
110 current_stats_.enable_custom_labels = enable_custom_labels;
111
112 // Update activity time
113 last_activity_ = std::chrono::steady_clock::now();
114}
115
116// These methods are already defined in the header as inline, removing
117// duplicates
118
120 switch (usage) {
122 return "Tile Painting";
124 return "Tile Selecting";
126 return "Rectangle Selection";
128 return "Color Painting";
130 return "Bitmap Editing";
132 return "Palette Editing";
134 return "BPP Conversion";
136 return "Performance Mode";
138 return "Entity Manipulation";
140 return "Unknown";
141 default:
142 return "Unknown";
143 }
144}
145
147 switch (usage) {
149 return ImVec4(0.2F, 1.0F, 0.2F, 1.0F); // Green
151 return ImVec4(0.2F, 0.8F, 1.0F, 1.0F); // Blue
153 return ImVec4(1.0F, 0.8F, 0.2F, 1.0F); // Yellow
155 return ImVec4(1.0F, 0.2F, 1.0F, 1.0F); // Magenta
157 return ImVec4(1.0F, 0.5F, 0.2F, 1.0F); // Orange
159 return ImVec4(0.8F, 0.2F, 1.0F, 1.0F); // Purple
161 return ImVec4(0.2F, 1.0F, 1.0F, 1.0F); // Cyan
163 return ImVec4(1.0F, 0.2F, 0.2F, 1.0F); // Red
165 return ImVec4(0.4F, 0.8F, 1.0F, 1.0F); // Light Blue
167 return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
168 default:
169 return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
170 }
171}
172
173std::vector<std::string> CanvasUsageTracker::GetUsageRecommendations() const {
174 std::vector<std::string> recommendations;
175
176 // Analyze usage patterns and provide recommendations
177 if (current_stats_.mouse_clicks > 100) {
178 recommendations.push_back(
179 "Consider using keyboard shortcuts to reduce mouse usage");
180 }
181
183 recommendations.push_back(
184 "Frequent context menu usage - consider adding toolbar buttons");
185 }
186
187 if (current_stats_.modal_opens > 10) {
188 recommendations.push_back(
189 "Many modal dialogs opened - consider persistent panels");
190 }
191
193 recommendations.push_back(
194 "Operations are slow - check performance optimization");
195 }
196
198 recommendations.push_back(
199 "Frequent mode switching - consider mode-specific toolbars");
200 }
201
202 return recommendations;
203}
204
206 std::ostringstream report;
207
208 report << "Canvas Usage Report for: " << canvas_id_ << "\n";
209 report << "==========================================\n\n";
210
211 // Session information
212 auto now = std::chrono::steady_clock::now();
213 auto session_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
214 now - session_start_);
215
216 report << "Session Information:\n";
217 report << " Duration: " << FormatDuration(session_duration) << "\n";
218 report << " Current Mode: " << GetUsageModeName(current_stats_.usage_mode)
219 << "\n";
220 report << " Mode Changes: " << current_stats_.mode_changes << "\n\n";
221
222 // Interaction statistics
223 report << "Interaction Statistics:\n";
224 report << " Mouse Clicks: " << current_stats_.mouse_clicks << "\n";
225 report << " Mouse Drags: " << current_stats_.mouse_drags << "\n";
226 report << " Context Menu Opens: " << current_stats_.context_menu_opens
227 << "\n";
228 report << " Modal Opens: " << current_stats_.modal_opens << "\n";
229 report << " Tool Changes: " << current_stats_.tool_changes << "\n\n";
230
231 // Performance statistics
232 report << "Performance Statistics:\n";
233 report << " Total Operations: " << current_stats_.total_operations << "\n";
234 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
236 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
238
239 // Canvas state
240 report << "Canvas State:\n";
241 report << " Canvas Size: " << static_cast<int>(current_stats_.canvas_size.x)
242 << " x " << static_cast<int>(current_stats_.canvas_size.y) << "\n";
243 report << " Content Size: "
244 << static_cast<int>(current_stats_.content_size.x) << " x "
245 << static_cast<int>(current_stats_.content_size.y) << "\n";
246 report << " Global Scale: " << std::fixed << std::setprecision(2)
247 << current_stats_.global_scale << "\n";
248 report << " Grid Step: " << std::fixed << std::setprecision(1)
249 << current_stats_.grid_step << "\n";
250 report << " Grid Enabled: " << (current_stats_.enable_grid ? "Yes" : "No")
251 << "\n";
252 report << " Hex Labels: "
253 << (current_stats_.enable_hex_labels ? "Yes" : "No") << "\n";
254 report << " Custom Labels: "
255 << (current_stats_.enable_custom_labels ? "Yes" : "No") << "\n\n";
256
257 // Operation breakdown
258 if (!operation_times_.empty()) {
259 report << "Operation Breakdown:\n";
260 for (const auto& [operation, times] : operation_times_) {
261 double avg_time = CalculateAverageOperationTime(operation);
262 report << " " << operation << ": " << times.size() << " operations, "
263 << "avg " << std::fixed << std::setprecision(2) << avg_time
264 << " ms\n";
265 }
266 report << "\n";
267 }
268
269 // Recommendations
270 auto recommendations = GetUsageRecommendations();
271 if (!recommendations.empty()) {
272 report << "Recommendations:\n";
273 for (const auto& rec : recommendations) {
274 report << " • " << rec << "\n";
275 }
276 }
277
278 return report.str();
279}
280
290
296
298 // Update final statistics
301
302 // Save final stats
304
305 LOG_DEBUG(
306 "CanvasUsage", "Canvas %s: Session ended. Duration: %s, Operations: %d",
307 canvas_id_.c_str(),
308 FormatDuration(std::chrono::duration_cast<std::chrono::milliseconds>(
309 std::chrono::steady_clock::now() - session_start_))
310 .c_str(),
312}
313
315 auto now = std::chrono::steady_clock::now();
316 auto time_since_activity =
317 std::chrono::duration_cast<std::chrono::milliseconds>(now -
319
320 if (time_since_activity.count() < 5000) { // 5 seconds threshold
321 current_stats_.active_time += time_since_activity;
322 }
323}
324
326 auto now = std::chrono::steady_clock::now();
327 auto time_since_activity =
328 std::chrono::duration_cast<std::chrono::milliseconds>(now -
330
331 if (time_since_activity.count() >= 5000) { // 5 seconds threshold
332 current_stats_.idle_time += time_since_activity;
333 }
334}
335
337 // Update final times
340
341 // Calculate total time
344
345 // Save to history
347
348 // Reset for next session
350 current_stats_.session_start = std::chrono::steady_clock::now();
351}
352
354 const std::string& operation_name) const {
355 auto it = operation_times_.find(operation_name);
356 if (it == operation_times_.end() || it->second.empty()) {
357 return 0.0;
358 }
359
360 double total = 0.0;
361 for (double time : it->second) {
362 total += time;
363 }
364
365 return total / it->second.size();
366}
367
369 const std::chrono::milliseconds& duration) const {
370 auto total_ms = duration.count();
371 auto hours = total_ms / 3600000;
372 auto minutes = (total_ms % 3600000) / 60000;
373 auto seconds = (total_ms % 60000) / 1000;
374
375 std::ostringstream ss;
376 if (hours > 0) {
377 ss << hours << "h " << minutes << "m " << seconds << "s";
378 } else if (minutes > 0) {
379 ss << minutes << "m " << seconds << "s";
380 } else {
381 ss << seconds << "s";
382 }
383
384 return ss.str();
385}
386
387// CanvasUsageManager implementation
388
390 static CanvasUsageManager instance;
391 return instance;
392}
393
395 const std::string& canvas_id, std::shared_ptr<CanvasUsageTracker> tracker) {
396 trackers_[canvas_id] = tracker;
397 LOG_DEBUG("CanvasUsage", "Registered usage tracker for canvas: %s",
398 canvas_id.c_str());
399}
400
401std::shared_ptr<CanvasUsageTracker> CanvasUsageManager::GetTracker(
402 const std::string& canvas_id) {
403 auto it = trackers_.find(canvas_id);
404 if (it != trackers_.end()) {
405 return it->second;
406 }
407 return nullptr;
408}
409
411 CanvasUsageStats global_stats;
412
413 for (const auto& [id, tracker] : trackers_) {
414 const auto& stats = tracker->GetCurrentStats();
415
416 global_stats.mouse_clicks += stats.mouse_clicks;
417 global_stats.mouse_drags += stats.mouse_drags;
418 global_stats.context_menu_opens += stats.context_menu_opens;
419 global_stats.modal_opens += stats.modal_opens;
420 global_stats.tool_changes += stats.tool_changes;
421 global_stats.mode_changes += stats.mode_changes;
422 global_stats.total_operations += stats.total_operations;
423
424 // Update averages
425 if (stats.average_operation_time_ms >
426 global_stats.average_operation_time_ms) {
427 global_stats.average_operation_time_ms = stats.average_operation_time_ms;
428 }
429 if (stats.max_operation_time_ms > global_stats.max_operation_time_ms) {
430 global_stats.max_operation_time_ms = stats.max_operation_time_ms;
431 }
432 }
433
434 return global_stats;
435}
436
438 std::ostringstream report;
439
440 report << "Global Canvas Usage Report\n";
441 report << "==========================\n\n";
442
443 report << "Registered Canvases: " << trackers_.size() << "\n\n";
444
445 for (const auto& [id, tracker] : trackers_) {
446 report << "Canvas: " << id << "\n";
447 report << "----------------------------------------\n";
448 report << tracker->ExportUsageReport() << "\n\n";
449 }
450
451 // Global summary
452 auto global_stats = GetGlobalStats();
453 report << "Global Summary:\n";
454 report << " Total Mouse Clicks: " << global_stats.mouse_clicks << "\n";
455 report << " Total Operations: " << global_stats.total_operations << "\n";
456 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
457 << global_stats.average_operation_time_ms << " ms\n";
458 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
459 << global_stats.max_operation_time_ms << " ms\n";
460
461 return report.str();
462}
463
465 for (auto& [id, tracker] : trackers_) {
466 tracker->ClearHistory();
467 }
468 trackers_.clear();
469 LOG_DEBUG("CanvasUsage", "Cleared all canvas usage trackers");
470}
471
472} // namespace gui
473} // namespace yaze
Global canvas usage tracker manager.
std::unordered_map< std::string, std::shared_ptr< CanvasUsageTracker > > trackers_
static CanvasUsageManager & Get()
std::shared_ptr< CanvasUsageTracker > GetTracker(const std::string &canvas_id)
Get tracker for canvas.
std::string ExportGlobalReport() const
Export global usage report.
CanvasUsageStats GetGlobalStats() const
Get global usage statistics.
void ClearAllTrackers()
Clear all trackers.
void RegisterTracker(const std::string &canvas_id, std::shared_ptr< CanvasUsageTracker > tracker)
Register a canvas tracker.
void RecordOperation(const std::string &operation_name, double time_ms)
Record operation timing.
std::vector< std::string > GetUsageRecommendations() const
Get usage recommendations.
void SetUsageMode(CanvasUsage usage)
Set the current usage mode.
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.
std::string ExportUsageReport() const
Export usage report.
void ClearHistory()
Clear usage history.
std::chrono::steady_clock::time_point last_activity_
std::string FormatDuration(const std::chrono::milliseconds &duration) const
std::unordered_map< std::string, std::vector< double > > operation_times_
double CalculateAverageOperationTime(const std::string &operation_name) const
void RecordInteraction(CanvasInteraction interaction, const std::string &details="")
Record an interaction.
std::vector< std::pair< CanvasInteraction, std::string > > interaction_history_
std::chrono::steady_clock::time_point session_start_
ImVec4 GetUsageModeColor(CanvasUsage usage) const
Get usage mode color for UI.
std::string GetUsageModeName(CanvasUsage usage) const
Get usage mode name.
void Initialize(const std::string &canvas_id)
Initialize the usage tracker.
std::vector< CanvasUsageStats > usage_history_
#define LOG_DEBUG(category, format,...)
Definition log.h:103
CanvasUsage
Canvas usage patterns and tracking.
CanvasInteraction
Canvas interaction types.
Canvas usage statistics.
std::chrono::milliseconds total_time
std::chrono::steady_clock::time_point session_start
std::chrono::milliseconds idle_time
std::chrono::milliseconds active_time