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 {
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,
101 float grid_step,
102 bool enable_grid,
103 bool enable_hex_labels,
104 bool enable_custom_labels) {
105 current_stats_.canvas_size = canvas_size;
106 current_stats_.content_size = content_size;
107 current_stats_.global_scale = global_scale;
108 current_stats_.grid_step = grid_step;
109 current_stats_.enable_grid = enable_grid;
110 current_stats_.enable_hex_labels = enable_hex_labels;
111 current_stats_.enable_custom_labels = enable_custom_labels;
112
113 // Update activity time
114 last_activity_ = std::chrono::steady_clock::now();
115}
116
117// These methods are already defined in the header as inline, removing duplicates
118
120 switch (usage) {
121 case CanvasUsage::kTilePainting: return "Tile Painting";
122 case CanvasUsage::kTileSelecting: return "Tile Selecting";
123 case CanvasUsage::kSelectRectangle: return "Rectangle Selection";
124 case CanvasUsage::kColorPainting: return "Color Painting";
125 case CanvasUsage::kBitmapEditing: return "Bitmap Editing";
126 case CanvasUsage::kPaletteEditing: return "Palette Editing";
127 case CanvasUsage::kBppConversion: return "BPP Conversion";
128 case CanvasUsage::kPerformanceMode: return "Performance Mode";
129 case CanvasUsage::kEntityManipulation: return "Entity Manipulation";
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::kEntityManipulation: return ImVec4(0.4F, 0.8F, 1.0F, 1.0F); // Light Blue
146 case CanvasUsage::kUnknown: return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
147 default: return ImVec4(0.7F, 0.7F, 0.7F, 1.0F); // Gray
148 }
149}
150
151std::vector<std::string> CanvasUsageTracker::GetUsageRecommendations() const {
152 std::vector<std::string> recommendations;
153
154 // Analyze usage patterns and provide recommendations
155 if (current_stats_.mouse_clicks > 100) {
156 recommendations.push_back("Consider using keyboard shortcuts to reduce mouse usage");
157 }
158
160 recommendations.push_back("Frequent context menu usage - consider adding toolbar buttons");
161 }
162
163 if (current_stats_.modal_opens > 10) {
164 recommendations.push_back("Many modal dialogs opened - consider persistent panels");
165 }
166
168 recommendations.push_back("Operations are slow - check performance optimization");
169 }
170
172 recommendations.push_back("Frequent mode switching - consider mode-specific toolbars");
173 }
174
175 return recommendations;
176}
177
179 std::ostringstream report;
180
181 report << "Canvas Usage Report for: " << canvas_id_ << "\n";
182 report << "==========================================\n\n";
183
184 // Session information
185 auto now = std::chrono::steady_clock::now();
186 auto session_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
187 now - session_start_);
188
189 report << "Session Information:\n";
190 report << " Duration: " << FormatDuration(session_duration) << "\n";
191 report << " Current Mode: " << GetUsageModeName(current_stats_.usage_mode) << "\n";
192 report << " Mode Changes: " << current_stats_.mode_changes << "\n\n";
193
194 // Interaction statistics
195 report << "Interaction Statistics:\n";
196 report << " Mouse Clicks: " << current_stats_.mouse_clicks << "\n";
197 report << " Mouse Drags: " << current_stats_.mouse_drags << "\n";
198 report << " Context Menu Opens: " << current_stats_.context_menu_opens << "\n";
199 report << " Modal Opens: " << current_stats_.modal_opens << "\n";
200 report << " Tool Changes: " << current_stats_.tool_changes << "\n\n";
201
202 // Performance statistics
203 report << "Performance Statistics:\n";
204 report << " Total Operations: " << current_stats_.total_operations << "\n";
205 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
207 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
209
210 // Canvas state
211 report << "Canvas State:\n";
212 report << " Canvas Size: " << static_cast<int>(current_stats_.canvas_size.x)
213 << " x " << static_cast<int>(current_stats_.canvas_size.y) << "\n";
214 report << " Content Size: " << static_cast<int>(current_stats_.content_size.x)
215 << " x " << static_cast<int>(current_stats_.content_size.y) << "\n";
216 report << " Global Scale: " << std::fixed << std::setprecision(2)
217 << current_stats_.global_scale << "\n";
218 report << " Grid Step: " << std::fixed << std::setprecision(1)
219 << current_stats_.grid_step << "\n";
220 report << " Grid Enabled: " << (current_stats_.enable_grid ? "Yes" : "No") << "\n";
221 report << " Hex Labels: " << (current_stats_.enable_hex_labels ? "Yes" : "No") << "\n";
222 report << " Custom Labels: " << (current_stats_.enable_custom_labels ? "Yes" : "No") << "\n\n";
223
224 // Operation breakdown
225 if (!operation_times_.empty()) {
226 report << "Operation Breakdown:\n";
227 for (const auto& [operation, times] : operation_times_) {
228 double avg_time = CalculateAverageOperationTime(operation);
229 report << " " << operation << ": " << times.size() << " operations, "
230 << "avg " << std::fixed << std::setprecision(2) << avg_time << " ms\n";
231 }
232 report << "\n";
233 }
234
235 // Recommendations
236 auto recommendations = GetUsageRecommendations();
237 if (!recommendations.empty()) {
238 report << "Recommendations:\n";
239 for (const auto& rec : recommendations) {
240 report << " • " << rec << "\n";
241 }
242 }
243
244 return report.str();
245}
246
256
262
264 // Update final statistics
267
268 // Save final stats
270
271 LOG_DEBUG("CanvasUsage", "Canvas %s: Session ended. Duration: %s, Operations: %d",
272 canvas_id_.c_str(),
273 FormatDuration(std::chrono::duration_cast<std::chrono::milliseconds>(
274 std::chrono::steady_clock::now() - session_start_)).c_str(),
276}
277
279 auto now = std::chrono::steady_clock::now();
280 auto time_since_activity = std::chrono::duration_cast<std::chrono::milliseconds>(
281 now - last_activity_);
282
283 if (time_since_activity.count() < 5000) { // 5 seconds threshold
284 current_stats_.active_time += time_since_activity;
285 }
286}
287
289 auto now = std::chrono::steady_clock::now();
290 auto time_since_activity = std::chrono::duration_cast<std::chrono::milliseconds>(
291 now - last_activity_);
292
293 if (time_since_activity.count() >= 5000) { // 5 seconds threshold
294 current_stats_.idle_time += time_since_activity;
295 }
296}
297
299 // Update final times
302
303 // Calculate total time
305
306 // Save to history
308
309 // Reset for next session
311 current_stats_.session_start = std::chrono::steady_clock::now();
312}
313
314double CanvasUsageTracker::CalculateAverageOperationTime(const std::string& operation_name) const {
315 auto it = operation_times_.find(operation_name);
316 if (it == operation_times_.end() || it->second.empty()) {
317 return 0.0;
318 }
319
320 double total = 0.0;
321 for (double time : it->second) {
322 total += time;
323 }
324
325 return total / it->second.size();
326}
327
328std::string CanvasUsageTracker::FormatDuration(const std::chrono::milliseconds& duration) const {
329 auto total_ms = duration.count();
330 auto hours = total_ms / 3600000;
331 auto minutes = (total_ms % 3600000) / 60000;
332 auto seconds = (total_ms % 60000) / 1000;
333
334 std::ostringstream ss;
335 if (hours > 0) {
336 ss << hours << "h " << minutes << "m " << seconds << "s";
337 } else if (minutes > 0) {
338 ss << minutes << "m " << seconds << "s";
339 } else {
340 ss << seconds << "s";
341 }
342
343 return ss.str();
344}
345
346// CanvasUsageManager implementation
347
349 static CanvasUsageManager instance;
350 return instance;
351}
352
353void CanvasUsageManager::RegisterTracker(const std::string& canvas_id,
354 std::shared_ptr<CanvasUsageTracker> tracker) {
355 trackers_[canvas_id] = tracker;
356 LOG_DEBUG("CanvasUsage", "Registered usage tracker for canvas: %s", canvas_id.c_str());
357}
358
359std::shared_ptr<CanvasUsageTracker> CanvasUsageManager::GetTracker(const std::string& canvas_id) {
360 auto it = trackers_.find(canvas_id);
361 if (it != trackers_.end()) {
362 return it->second;
363 }
364 return nullptr;
365}
366
368 CanvasUsageStats global_stats;
369
370 for (const auto& [id, tracker] : trackers_) {
371 const auto& stats = tracker->GetCurrentStats();
372
373 global_stats.mouse_clicks += stats.mouse_clicks;
374 global_stats.mouse_drags += stats.mouse_drags;
375 global_stats.context_menu_opens += stats.context_menu_opens;
376 global_stats.modal_opens += stats.modal_opens;
377 global_stats.tool_changes += stats.tool_changes;
378 global_stats.mode_changes += stats.mode_changes;
379 global_stats.total_operations += stats.total_operations;
380
381 // Update averages
382 if (stats.average_operation_time_ms > global_stats.average_operation_time_ms) {
383 global_stats.average_operation_time_ms = stats.average_operation_time_ms;
384 }
385 if (stats.max_operation_time_ms > global_stats.max_operation_time_ms) {
386 global_stats.max_operation_time_ms = stats.max_operation_time_ms;
387 }
388 }
389
390 return global_stats;
391}
392
394 std::ostringstream report;
395
396 report << "Global Canvas Usage Report\n";
397 report << "==========================\n\n";
398
399 report << "Registered Canvases: " << trackers_.size() << "\n\n";
400
401 for (const auto& [id, tracker] : trackers_) {
402 report << "Canvas: " << id << "\n";
403 report << "----------------------------------------\n";
404 report << tracker->ExportUsageReport() << "\n\n";
405 }
406
407 // Global summary
408 auto global_stats = GetGlobalStats();
409 report << "Global Summary:\n";
410 report << " Total Mouse Clicks: " << global_stats.mouse_clicks << "\n";
411 report << " Total Operations: " << global_stats.total_operations << "\n";
412 report << " Average Operation Time: " << std::fixed << std::setprecision(2)
413 << global_stats.average_operation_time_ms << " ms\n";
414 report << " Max Operation Time: " << std::fixed << std::setprecision(2)
415 << global_stats.max_operation_time_ms << " ms\n";
416
417 return report.str();
418}
419
421 for (auto& [id, tracker] : trackers_) {
422 tracker->ClearHistory();
423 }
424 trackers_.clear();
425 LOG_DEBUG("CanvasUsage", "Cleared all canvas usage trackers");
426}
427
428} // namespace gui
429} // 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:104
CanvasUsage
Canvas usage patterns and tracking.
CanvasInteraction
Canvas interaction types.
Main namespace for the application.
Definition controller.cc:20
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