From 8d3a049f4da909142bb852a936c4b772501d54fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Wed, 19 Feb 2025 16:32:27 +0100 Subject: [PATCH] refactor(wip): drop heartbeat padding in summary aggregation (see #675) --- coverage/coverage.out | 1015 +++++++++++----------- models/user.go | 9 +- repositories/heartbeat.go | 1 - routes/settings.go | 5 +- scripts/aggregate_durations_mysql.sql | 18 +- scripts/aggregate_durations_postgres.sql | 19 +- services/duration.go | 68 +- services/duration_test.go | 16 +- views/settings.tpl.html | 4 +- 9 files changed, 571 insertions(+), 584 deletions(-) diff --git a/coverage/coverage.out b/coverage/coverage.out index c277565..8d0efa1 100644 --- a/coverage/coverage.out +++ b/coverage/coverage.out @@ -290,19 +290,16 @@ github.com/muety/wakapi/config/sentry.go:116.2,116.11 1 0 github.com/muety/wakapi/config/session.go:9.46,10.25 1 0 github.com/muety/wakapi/config/session.go:10.25,12.3 1 0 github.com/muety/wakapi/config/session.go:13.2,13.21 1 0 -github.com/muety/wakapi/helpers/date.go:18.73,19.58 1 0 -github.com/muety/wakapi/helpers/date.go:19.58,21.3 1 0 -github.com/muety/wakapi/helpers/date.go:22.2,22.87 1 0 -github.com/muety/wakapi/helpers/date.go:22.87,24.3 1 0 -github.com/muety/wakapi/helpers/date.go:25.2,25.64 1 0 -github.com/muety/wakapi/helpers/date.go:28.40,30.2 1 0 -github.com/muety/wakapi/helpers/date.go:32.44,34.2 1 0 -github.com/muety/wakapi/helpers/date.go:36.49,38.2 1 0 -github.com/muety/wakapi/helpers/date.go:40.51,42.39 2 0 -github.com/muety/wakapi/helpers/date.go:42.39,44.3 1 0 -github.com/muety/wakapi/helpers/date.go:45.2,45.28 1 0 -github.com/muety/wakapi/helpers/date.go:48.45,50.2 1 0 -github.com/muety/wakapi/helpers/date.go:52.50,58.2 5 0 +github.com/muety/wakapi/helpers/date.go:17.73,18.58 1 0 +github.com/muety/wakapi/helpers/date.go:18.58,20.3 1 0 +github.com/muety/wakapi/helpers/date.go:21.2,21.87 1 0 +github.com/muety/wakapi/helpers/date.go:21.87,23.3 1 0 +github.com/muety/wakapi/helpers/date.go:24.2,24.64 1 0 +github.com/muety/wakapi/helpers/date.go:27.40,29.2 1 0 +github.com/muety/wakapi/helpers/date.go:31.44,33.2 1 0 +github.com/muety/wakapi/helpers/date.go:35.49,37.2 1 0 +github.com/muety/wakapi/helpers/date.go:39.45,41.2 1 0 +github.com/muety/wakapi/helpers/date.go:43.50,49.2 5 0 github.com/muety/wakapi/helpers/http.go:11.94,13.16 2 0 github.com/muety/wakapi/helpers/http.go:13.16,15.3 1 0 github.com/muety/wakapi/helpers/http.go:17.2,17.107 1 0 @@ -428,6 +425,91 @@ github.com/muety/wakapi/middlewares/custom/wakatime.go:183.37,186.3 2 0 github.com/muety/wakapi/middlewares/custom/wakatime.go:188.2,189.62 2 0 github.com/muety/wakapi/middlewares/custom/wakatime.go:189.62,191.3 1 0 github.com/muety/wakapi/middlewares/custom/wakatime.go:192.2,194.12 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:13.65,16.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:18.76,21.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:23.93,26.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:28.109,31.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:33.109,36.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:38.78,41.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:43.52,46.2 2 0 +github.com/muety/wakapi/mocks/alias_repository.go:48.59,51.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:12.57,15.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:17.59,20.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:22.92,25.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:27.73,30.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:32.89,35.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:37.106,40.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:42.75,45.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:47.58,50.2 2 0 +github.com/muety/wakapi/mocks/alias_service.go:52.65,55.2 2 0 +github.com/muety/wakapi/mocks/base_repository.go:11.52,14.2 2 0 +github.com/muety/wakapi/mocks/base_repository.go:16.73,19.2 2 0 +github.com/muety/wakapi/mocks/base_repository.go:21.74,24.2 2 0 +github.com/muety/wakapi/mocks/duration_service.go:13.132,16.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:14.66,17.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:19.73,22.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:24.61,27.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:29.78,32.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:34.98,37.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:39.126,42.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:44.160,47.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:49.80,52.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:54.94,57.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:59.113,62.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:64.113,67.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:69.91,72.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:74.67,77.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:79.67,82.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:84.86,87.2 2 0 +github.com/muety/wakapi/mocks/heartbeat_service.go:89.146,92.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:12.83,15.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:17.78,20.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:22.87,25.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:27.73,30.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:32.60,35.2 2 0 +github.com/muety/wakapi/mocks/key_value_service.go:37.69,40.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:12.81,15.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:17.87,20.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:22.105,25.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:27.113,30.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:32.96,35.2 2 0 +github.com/muety/wakapi/mocks/project_label_service.go:37.72,40.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:14.65,17.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:19.69,22.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:24.120,27.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:29.79,32.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:34.62,37.2 2 0 +github.com/muety/wakapi/mocks/summary_repository.go:39.81,42.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:14.159,17.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:19.126,22.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:24.127,27.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:29.78,32.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:34.59,37.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:39.78,42.2 2 0 +github.com/muety/wakapi/mocks/summary_service.go:44.62,47.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:12.71,15.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:17.72,20.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:22.74,25.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:27.79,30.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:32.60,35.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:37.75,40.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:42.71,45.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:47.86,50.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:52.79,54.23 1 0 +github.com/muety/wakapi/mocks/user_service.go:57.75,60.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:62.85,65.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:67.69,70.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:72.50,75.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:77.104,80.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:82.75,85.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:87.59,90.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:92.80,95.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:97.81,100.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:102.109,105.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:107.87,110.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:112.92,115.2 2 0 +github.com/muety/wakapi/mocks/user_service.go:117.40,119.2 1 0 +github.com/muety/wakapi/mocks/user_service.go:121.52,123.2 1 0 github.com/muety/wakapi/migrations/20201103_rename_language_mappings_table.go:10.13,13.50 1 0 github.com/muety/wakapi/migrations/20201103_rename_language_mappings_table.go:13.50,18.39 4 0 github.com/muety/wakapi/migrations/20201103_rename_language_mappings_table.go:18.39,20.89 2 0 @@ -728,91 +810,6 @@ github.com/muety/wakapi/migrations/shared.go:14.64,17.3 2 0 github.com/muety/wakapi/migrations/shared.go:18.2,18.14 1 0 github.com/muety/wakapi/migrations/shared.go:21.42,25.23 1 0 github.com/muety/wakapi/migrations/shared.go:25.23,27.3 1 0 -github.com/muety/wakapi/mocks/alias_repository.go:13.65,16.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:18.76,21.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:23.93,26.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:28.109,31.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:33.109,36.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:38.78,41.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:43.52,46.2 2 0 -github.com/muety/wakapi/mocks/alias_repository.go:48.59,51.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:12.57,15.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:17.59,20.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:22.92,25.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:27.73,30.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:32.89,35.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:37.106,40.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:42.75,45.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:47.58,50.2 2 0 -github.com/muety/wakapi/mocks/alias_service.go:52.65,55.2 2 0 -github.com/muety/wakapi/mocks/base_repository.go:11.52,14.2 2 0 -github.com/muety/wakapi/mocks/base_repository.go:16.73,19.2 2 0 -github.com/muety/wakapi/mocks/base_repository.go:21.74,24.2 2 0 -github.com/muety/wakapi/mocks/duration_service.go:13.132,16.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:14.66,17.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:19.73,22.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:24.61,27.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:29.78,32.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:34.98,37.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:39.126,42.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:44.160,47.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:49.80,52.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:54.94,57.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:59.113,62.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:64.113,67.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:69.91,72.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:74.67,77.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:79.67,82.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:84.86,87.2 2 0 -github.com/muety/wakapi/mocks/heartbeat_service.go:89.146,92.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:12.83,15.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:17.78,20.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:22.87,25.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:27.73,30.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:32.60,35.2 2 0 -github.com/muety/wakapi/mocks/key_value_service.go:37.69,40.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:12.81,15.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:17.87,20.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:22.105,25.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:27.113,30.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:32.96,35.2 2 0 -github.com/muety/wakapi/mocks/project_label_service.go:37.72,40.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:14.65,17.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:19.69,22.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:24.120,27.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:29.79,32.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:34.62,37.2 2 0 -github.com/muety/wakapi/mocks/summary_repository.go:39.81,42.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:14.159,17.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:19.126,22.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:24.127,27.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:29.78,32.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:34.59,37.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:39.78,42.2 2 0 -github.com/muety/wakapi/mocks/summary_service.go:44.62,47.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:12.71,15.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:17.72,20.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:22.74,25.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:27.79,30.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:32.60,35.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:37.75,40.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:42.71,45.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:47.86,50.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:52.79,54.23 1 0 -github.com/muety/wakapi/mocks/user_service.go:57.75,60.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:62.85,65.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:67.69,70.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:72.50,75.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:77.104,80.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:82.75,85.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:87.59,90.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:92.80,95.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:97.81,100.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:102.109,105.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:107.87,110.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:112.92,115.2 2 0 -github.com/muety/wakapi/mocks/user_service.go:117.40,119.2 1 0 -github.com/muety/wakapi/mocks/user_service.go:121.52,123.2 1 0 github.com/muety/wakapi/middlewares/authenticate.go:36.91,43.2 1 1 github.com/muety/wakapi/middlewares/authenticate.go:45.91,48.2 2 0 github.com/muety/wakapi/middlewares/authenticate.go:50.100,53.2 2 0 @@ -923,26 +920,6 @@ github.com/muety/wakapi/middlewares/sentry.go:16.43,20.3 1 0 github.com/muety/wakapi/middlewares/sentry.go:23.78,26.54 3 0 github.com/muety/wakapi/middlewares/sentry.go:26.54,27.43 1 0 github.com/muety/wakapi/middlewares/sentry.go:27.43,29.4 1 0 -github.com/muety/wakapi/models/metrics/counter_metric.go:12.37,14.2 1 0 -github.com/muety/wakapi/models/metrics/counter_metric.go:16.39,18.2 1 0 -github.com/muety/wakapi/models/metrics/counter_metric.go:20.40,22.2 1 0 -github.com/muety/wakapi/models/metrics/gauge_metric.go:12.35,14.2 1 0 -github.com/muety/wakapi/models/metrics/gauge_metric.go:16.37,18.2 1 0 -github.com/muety/wakapi/models/metrics/gauge_metric.go:20.38,22.2 1 0 -github.com/muety/wakapi/models/metrics/label.go:15.32,17.22 2 0 -github.com/muety/wakapi/models/metrics/label.go:17.22,19.3 1 0 -github.com/muety/wakapi/models/metrics/label.go:20.2,20.17 1 0 -github.com/muety/wakapi/models/metrics/label.go:20.17,22.3 1 0 -github.com/muety/wakapi/models/metrics/label.go:23.2,23.62 1 0 -github.com/muety/wakapi/models/metrics/label.go:26.31,28.2 1 0 -github.com/muety/wakapi/models/metrics/metric.go:14.42,16.22 2 0 -github.com/muety/wakapi/models/metrics/metric.go:16.22,17.44 1 0 -github.com/muety/wakapi/models/metrics/metric.go:17.44,20.4 2 0 -github.com/muety/wakapi/models/metrics/metric.go:21.3,21.43 1 0 -github.com/muety/wakapi/models/metrics/metric.go:24.2,24.15 1 0 -github.com/muety/wakapi/models/metrics/metric.go:27.28,29.2 1 0 -github.com/muety/wakapi/models/metrics/metric.go:31.38,33.2 1 0 -github.com/muety/wakapi/models/metrics/metric.go:35.33,37.2 1 0 github.com/muety/wakapi/models/view/common.go:30.77,35.21 2 0 github.com/muety/wakapi/models/view/common.go:35.21,37.3 1 0 github.com/muety/wakapi/models/view/common.go:38.2,38.11 1 0 @@ -965,9 +942,7 @@ github.com/muety/wakapi/models/view/leaderboard.go:40.2,40.20 1 0 github.com/muety/wakapi/models/view/leaderboard.go:40.20,42.3 1 0 github.com/muety/wakapi/models/view/leaderboard.go:43.2,43.18 1 0 github.com/muety/wakapi/models/view/leaderboard.go:46.61,48.2 1 0 -github.com/muety/wakapi/models/view/leaderboard.go:50.55,52.19 2 0 -github.com/muety/wakapi/models/view/leaderboard.go:52.19,54.3 1 0 -github.com/muety/wakapi/models/view/leaderboard.go:55.2,55.56 1 0 +github.com/muety/wakapi/models/view/leaderboard.go:50.55,52.2 1 0 github.com/muety/wakapi/models/view/login.go:16.64,19.2 2 0 github.com/muety/wakapi/models/view/login.go:21.62,24.2 2 0 github.com/muety/wakapi/models/view/projects.go:19.58,21.2 1 0 @@ -1067,6 +1042,26 @@ github.com/muety/wakapi/models/compat/wakatime/v1/user.go:47.43,49.3 1 0 github.com/muety/wakapi/models/compat/wakatime/v1/user.go:51.2,60.3 1 0 github.com/muety/wakapi/models/compat/wakatime/v1/user.go:63.63,68.2 4 0 github.com/muety/wakapi/models/compat/shields/v1/badge.go:22.59,29.2 1 0 +github.com/muety/wakapi/models/metrics/counter_metric.go:12.37,14.2 1 0 +github.com/muety/wakapi/models/metrics/counter_metric.go:16.39,18.2 1 0 +github.com/muety/wakapi/models/metrics/counter_metric.go:20.40,22.2 1 0 +github.com/muety/wakapi/models/metrics/gauge_metric.go:12.35,14.2 1 0 +github.com/muety/wakapi/models/metrics/gauge_metric.go:16.37,18.2 1 0 +github.com/muety/wakapi/models/metrics/gauge_metric.go:20.38,22.2 1 0 +github.com/muety/wakapi/models/metrics/label.go:15.32,17.22 2 0 +github.com/muety/wakapi/models/metrics/label.go:17.22,19.3 1 0 +github.com/muety/wakapi/models/metrics/label.go:20.2,20.17 1 0 +github.com/muety/wakapi/models/metrics/label.go:20.17,22.3 1 0 +github.com/muety/wakapi/models/metrics/label.go:23.2,23.62 1 0 +github.com/muety/wakapi/models/metrics/label.go:26.31,28.2 1 0 +github.com/muety/wakapi/models/metrics/metric.go:14.42,16.22 2 0 +github.com/muety/wakapi/models/metrics/metric.go:16.22,17.44 1 0 +github.com/muety/wakapi/models/metrics/metric.go:17.44,20.4 2 0 +github.com/muety/wakapi/models/metrics/metric.go:21.3,21.43 1 0 +github.com/muety/wakapi/models/metrics/metric.go:24.2,24.15 1 0 +github.com/muety/wakapi/models/metrics/metric.go:27.28,29.2 1 0 +github.com/muety/wakapi/models/metrics/metric.go:31.38,33.2 1 0 +github.com/muety/wakapi/models/metrics/metric.go:35.33,37.2 1 0 github.com/muety/wakapi/repositories/alias.go:13.55,15.2 1 0 github.com/muety/wakapi/repositories/alias.go:17.61,19.50 2 0 github.com/muety/wakapi/repositories/alias.go:19.50,21.3 1 0 @@ -1114,71 +1109,71 @@ github.com/muety/wakapi/repositories/heartbeat.go:22.63,24.2 1 0 github.com/muety/wakapi/repositories/heartbeat.go:27.69,29.53 2 0 github.com/muety/wakapi/repositories/heartbeat.go:29.53,31.3 1 0 github.com/muety/wakapi/repositories/heartbeat.go:32.2,32.24 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:35.81,39.61 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:39.61,40.32 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:40.32,42.18 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:42.18,43.140 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:43.141,45.6 0 0 -github.com/muety/wakapi/repositories/heartbeat.go:45.11,47.6 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:50.3,50.13 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:53.2,57.41 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:57.41,59.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:60.2,60.12 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:63.93,70.38 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:70.38,72.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:73.2,73.24 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:76.117,86.38 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:86.38,88.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:89.2,89.24 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:92.112,100.39 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:100.39,102.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:103.2,103.24 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:106.152,117.50 4 0 -github.com/muety/wakapi/repositories/heartbeat.go:117.50,119.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:120.2,120.24 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:123.127,131.58 4 0 -github.com/muety/wakapi/repositories/heartbeat.go:131.58,133.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:134.2,134.23 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:137.79,146.2 3 0 -github.com/muety/wakapi/repositories/heartbeat.go:148.78,157.2 3 0 -github.com/muety/wakapi/repositories/heartbeat.go:159.80,160.42 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:160.42,166.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:168.2,168.16 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:168.16,172.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:173.2,173.19 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:176.77,181.35 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:181.35,183.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:184.2,184.19 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:187.97,191.26 3 0 -github.com/muety/wakapi/repositories/heartbeat.go:191.26,193.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:195.2,195.23 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:195.23,197.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:199.2,204.35 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:204.35,206.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:208.2,208.20 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:211.101,217.36 2 0 -github.com/muety/wakapi/repositories/heartbeat.go:217.36,219.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:220.2,220.21 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:223.63,226.48 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:226.48,228.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:229.2,229.12 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:232.69,235.48 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:235.48,237.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:238.2,238.12 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:241.88,245.48 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:245.48,247.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:248.2,248.12 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:251.141,270.27 4 0 -github.com/muety/wakapi/repositories/heartbeat.go:270.27,272.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:274.2,317.41 3 0 -github.com/muety/wakapi/repositories/heartbeat.go:317.41,319.3 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:321.2,321.26 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:324.97,325.35 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:325.35,326.91 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:326.91,328.18 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:328.18,330.5 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:331.4,331.14 1 0 -github.com/muety/wakapi/repositories/heartbeat.go:334.2,334.10 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:35.81,38.61 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:38.61,39.32 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:39.32,41.18 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:41.18,42.140 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:42.141,44.6 0 0 +github.com/muety/wakapi/repositories/heartbeat.go:44.11,46.6 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:49.3,49.13 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:52.2,56.41 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:56.41,58.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:59.2,59.12 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:62.93,69.38 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:69.38,71.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:72.2,72.24 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:75.117,85.38 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:85.38,87.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:88.2,88.24 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:91.112,99.39 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:99.39,101.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:102.2,102.24 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:105.152,116.50 4 0 +github.com/muety/wakapi/repositories/heartbeat.go:116.50,118.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:119.2,119.24 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:122.127,130.58 4 0 +github.com/muety/wakapi/repositories/heartbeat.go:130.58,132.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:133.2,133.23 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:136.79,145.2 3 0 +github.com/muety/wakapi/repositories/heartbeat.go:147.78,156.2 3 0 +github.com/muety/wakapi/repositories/heartbeat.go:158.80,159.42 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:159.42,165.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:167.2,167.16 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:167.16,171.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:172.2,172.19 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:175.77,180.35 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:180.35,182.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:183.2,183.19 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:186.97,190.26 3 0 +github.com/muety/wakapi/repositories/heartbeat.go:190.26,192.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:194.2,194.23 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:194.23,196.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:198.2,203.35 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:203.35,205.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:207.2,207.20 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:210.101,216.36 2 0 +github.com/muety/wakapi/repositories/heartbeat.go:216.36,218.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:219.2,219.21 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:222.63,225.48 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:225.48,227.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:228.2,228.12 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:231.69,234.48 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:234.48,236.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:237.2,237.12 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:240.88,244.48 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:244.48,246.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:247.2,247.12 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:250.141,269.27 4 0 +github.com/muety/wakapi/repositories/heartbeat.go:269.27,271.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:273.2,316.41 3 0 +github.com/muety/wakapi/repositories/heartbeat.go:316.41,318.3 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:320.2,320.26 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:323.97,324.35 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:324.35,325.91 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:325.91,327.18 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:327.18,329.5 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:330.4,330.14 1 0 +github.com/muety/wakapi/repositories/heartbeat.go:333.2,333.10 1 0 github.com/muety/wakapi/repositories/key_value.go:17.61,19.2 1 0 github.com/muety/wakapi/repositories/key_value.go:21.73,23.52 2 0 github.com/muety/wakapi/repositories/key_value.go:23.52,25.3 1 0 @@ -1782,63 +1777,45 @@ github.com/muety/wakapi/models/summary.go:477.35,479.2 1 0 github.com/muety/wakapi/models/summary.go:481.33,483.2 1 1 github.com/muety/wakapi/models/summary.go:485.43,487.2 1 1 github.com/muety/wakapi/models/summary.go:489.38,491.2 1 1 -github.com/muety/wakapi/models/user.go:20.13,22.2 1 1 -github.com/muety/wakapi/models/user.go:105.34,107.2 1 0 -github.com/muety/wakapi/models/user.go:109.36,110.22 1 1 -github.com/muety/wakapi/models/user.go:110.22,112.3 1 1 -github.com/muety/wakapi/models/user.go:113.2,114.16 2 1 -github.com/muety/wakapi/models/user.go:114.16,116.3 1 0 -github.com/muety/wakapi/models/user.go:117.2,117.11 1 1 -github.com/muety/wakapi/models/user.go:122.41,125.2 2 1 -github.com/muety/wakapi/models/user.go:127.53,130.54 3 0 -github.com/muety/wakapi/models/user.go:130.54,132.3 1 0 -github.com/muety/wakapi/models/user.go:133.2,133.51 1 0 -github.com/muety/wakapi/models/user.go:133.51,135.3 1 0 -github.com/muety/wakapi/models/user.go:136.2,136.20 1 0 -github.com/muety/wakapi/models/user.go:139.50,140.32 1 0 -github.com/muety/wakapi/models/user.go:140.32,142.3 1 0 -github.com/muety/wakapi/models/user.go:143.2,143.33 1 0 -github.com/muety/wakapi/models/user.go:147.52,148.28 1 0 -github.com/muety/wakapi/models/user.go:148.28,150.3 1 0 -github.com/muety/wakapi/models/user.go:151.2,151.17 1 0 -github.com/muety/wakapi/models/user.go:155.45,157.2 1 1 -github.com/muety/wakapi/models/user.go:159.51,161.2 1 1 -github.com/muety/wakapi/models/user.go:167.65,169.32 2 0 -github.com/muety/wakapi/models/user.go:169.32,171.3 1 0 -github.com/muety/wakapi/models/user.go:172.2,172.30 1 0 -github.com/muety/wakapi/models/user.go:172.30,174.3 1 0 -github.com/muety/wakapi/models/user.go:175.2,176.24 2 0 -github.com/muety/wakapi/models/user.go:179.39,181.55 2 1 -github.com/muety/wakapi/models/user.go:181.55,183.3 1 1 -github.com/muety/wakapi/models/user.go:185.2,185.51 1 1 -github.com/muety/wakapi/models/user.go:188.37,190.2 1 0 -github.com/muety/wakapi/models/user.go:192.43,195.2 1 0 -github.com/muety/wakapi/models/user.go:197.45,200.2 1 0 -github.com/muety/wakapi/models/user.go:202.33,209.2 2 0 -github.com/muety/wakapi/models/user.go:211.41,213.2 1 0 -github.com/muety/wakapi/models/user.go:215.45,217.2 1 0 -github.com/muety/wakapi/models/user.go:219.45,221.2 1 0 -github.com/muety/wakapi/models/user.go:223.59,225.2 1 0 -github.com/muety/wakapi/models/user.go:228.39,230.2 1 0 -github.com/muety/wakapi/models/user.go:232.39,235.2 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:26.112,33.2 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:35.58,38.2 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:50.68,52.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:52.16,55.3 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:57.2,58.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:58.16,62.3 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:63.2,66.50 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:66.50,69.3 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:71.2,79.16 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:79.16,83.3 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:85.2,87.46 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:90.144,92.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:92.16,94.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:96.2,103.29 3 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:103.29,105.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:107.2,115.16 2 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:115.16,117.3 1 0 -github.com/muety/wakapi/routes/compat/shields/v1/badge.go:119.2,119.36 1 0 +github.com/muety/wakapi/models/user.go:21.13,23.2 1 1 +github.com/muety/wakapi/models/user.go:106.34,108.2 1 0 +github.com/muety/wakapi/models/user.go:110.36,111.25 1 1 +github.com/muety/wakapi/models/user.go:111.25,113.6 1 1 +github.com/muety/wakapi/models/user.go:114.5,115.19 2 1 +github.com/muety/wakapi/models/user.go:115.19,117.6 1 0 +github.com/muety/wakapi/models/user.go:118.5,118.14 1 1 +github.com/muety/wakapi/models/user.go:123.41,126.2 2 1 +github.com/muety/wakapi/models/user.go:128.53,131.57 3 0 +github.com/muety/wakapi/models/user.go:131.57,133.6 1 0 +github.com/muety/wakapi/models/user.go:134.5,134.54 1 0 +github.com/muety/wakapi/models/user.go:134.54,136.6 1 0 +github.com/muety/wakapi/models/user.go:137.5,137.23 1 0 +github.com/muety/wakapi/models/user.go:140.50,141.35 1 0 +github.com/muety/wakapi/models/user.go:141.35,143.6 1 0 +github.com/muety/wakapi/models/user.go:144.5,144.36 1 0 +github.com/muety/wakapi/models/user.go:148.52,149.31 1 0 +github.com/muety/wakapi/models/user.go:149.31,151.6 1 0 +github.com/muety/wakapi/models/user.go:152.5,152.20 1 0 +github.com/muety/wakapi/models/user.go:156.45,158.2 1 1 +github.com/muety/wakapi/models/user.go:160.51,162.2 1 1 +github.com/muety/wakapi/models/user.go:168.65,170.35 2 0 +github.com/muety/wakapi/models/user.go:170.35,172.6 1 0 +github.com/muety/wakapi/models/user.go:173.5,173.33 1 0 +github.com/muety/wakapi/models/user.go:173.33,175.6 1 0 +github.com/muety/wakapi/models/user.go:176.5,177.27 2 0 +github.com/muety/wakapi/models/user.go:180.39,182.58 2 1 +github.com/muety/wakapi/models/user.go:182.58,184.6 1 1 +github.com/muety/wakapi/models/user.go:186.5,186.54 1 1 +github.com/muety/wakapi/models/user.go:189.37,191.2 1 0 +github.com/muety/wakapi/models/user.go:193.43,196.2 1 0 +github.com/muety/wakapi/models/user.go:198.45,201.2 1 0 +github.com/muety/wakapi/models/user.go:203.33,210.2 2 0 +github.com/muety/wakapi/models/user.go:212.41,214.2 1 0 +github.com/muety/wakapi/models/user.go:216.45,218.2 1 0 +github.com/muety/wakapi/models/user.go:220.45,222.2 1 0 +github.com/muety/wakapi/models/user.go:224.59,226.2 1 0 +github.com/muety/wakapi/models/user.go:229.39,231.2 1 0 +github.com/muety/wakapi/models/user.go:233.39,236.2 2 0 github.com/muety/wakapi/routes/utils/badge_utils.go:20.13,23.2 2 1 github.com/muety/wakapi/routes/utils/badge_utils.go:25.129,29.76 3 0 github.com/muety/wakapi/routes/utils/badge_utils.go:29.76,31.3 1 0 @@ -1909,189 +1886,6 @@ github.com/muety/wakapi/routes/utils/user_utils.go:35.63,37.3 1 1 github.com/muety/wakapi/routes/utils/user_utils.go:39.2,40.16 2 1 github.com/muety/wakapi/routes/utils/user_utils.go:40.16,42.3 1 0 github.com/muety/wakapi/routes/utils/user_utils.go:44.2,44.27 1 1 -github.com/muety/wakapi/routes/relay/relay.go:19.38,23.2 1 0 -github.com/muety/wakapi/routes/relay/relay.go:30.63,31.43 1 0 -github.com/muety/wakapi/routes/relay/relay.go:31.43,36.3 1 0 -github.com/muety/wakapi/routes/relay/relay.go:39.81,41.62 2 0 -github.com/muety/wakapi/routes/relay/relay.go:41.62,45.3 3 0 -github.com/muety/wakapi/routes/relay/relay.go:46.2,46.27 1 0 -github.com/muety/wakapi/routes/relay/relay.go:49.58,50.36 1 0 -github.com/muety/wakapi/routes/relay/relay.go:50.36,52.3 1 0 -github.com/muety/wakapi/routes/relay/relay.go:54.2,58.27 4 0 -github.com/muety/wakapi/routes/relay/relay.go:61.68,63.16 2 0 -github.com/muety/wakapi/routes/relay/relay.go:63.16,67.3 3 0 -github.com/muety/wakapi/routes/relay/relay.go:68.2,71.35 2 0 -github.com/muety/wakapi/routes/relay/relay.go:71.35,74.4 2 0 -github.com/muety/wakapi/routes/relay/relay.go:77.2,77.19 1 0 -github.com/muety/wakapi/routes/relay/relay.go:87.34,87.35 0 0 -github.com/muety/wakapi/routes/relay/relay.go:96.34,96.35 0 0 -github.com/muety/wakapi/routes/relay/relay.go:105.34,105.35 0 0 -github.com/muety/wakapi/routes/relay/relay.go:114.34,114.35 0 0 -github.com/muety/wakapi/routes/relay/relay.go:123.34,123.35 0 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:23.116,29.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:31.60,32.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:32.34,35.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:47.70,49.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:49.16,51.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:53.2,54.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:54.16,58.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:60.2,61.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:64.116,73.29 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:73.29,75.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:77.2,85.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:85.16,87.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:89.2,89.36 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:29.124,34.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:36.62,37.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:37.34,40.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:52.72,54.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:54.16,56.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:58.2,61.16 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:61.16,65.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:67.2,71.16 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:71.16,76.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:78.2,84.47 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:26.124,32.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:34.60,35.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:35.34,38.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:49.70,55.63 5 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:55.63,56.26 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:56.26,58.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:58.9,60.18 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:60.18,62.5 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:63.4,63.19 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:67.2,67.67 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:67.67,68.18 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:68.18,70.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:71.3,71.26 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:71.26,73.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:73.9,75.18 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:75.18,77.5 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:78.4,78.19 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:82.2,83.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:83.16,88.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:89.2,92.16 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:92.16,97.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:100.2,100.57 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:100.57,101.57 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:101.57,103.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:103.9,105.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:109.2,111.46 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:114.200,116.17 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:116.17,118.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:120.2,140.32 6 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:140.32,146.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:148.2,148.42 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:148.42,158.219 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:158.219,163.6 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:169.2,169.11 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:27.123,33.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:35.61,36.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:36.34,40.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:53.71,55.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:55.16,57.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:59.2,60.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:60.16,65.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:67.2,68.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:81.74,83.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:83.16,85.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:87.2,88.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:88.16,93.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:95.2,95.24 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:95.24,99.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:101.2,102.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:105.104,107.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:107.16,109.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:111.2,112.28 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:112.28,113.79 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:113.79,122.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:125.2,125.22 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:23.112,29.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:31.58,32.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:32.34,42.3 5 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:63.68,69.53 5 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:69.53,71.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:73.2,74.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:74.16,78.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:82.2,82.22 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:82.22,83.100 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:83.100,85.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:85.9,87.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:90.2,91.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:91.16,95.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:97.2,99.69 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:99.69,103.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:105.2,106.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:106.16,110.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:112.2,118.68 6 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:118.68,120.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:120.34,122.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:123.3,123.36 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:123.36,125.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:126.3,126.35 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:126.35,128.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:129.3,129.30 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:129.30,131.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:132.3,132.35 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:132.35,134.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:137.2,137.49 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:140.136,149.16 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:149.16,151.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:153.2,153.36 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:29.120,35.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:37.62,38.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:38.34,43.3 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:55.72,57.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:57.16,59.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:61.2,62.22 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:62.22,64.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:66.2,67.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:67.16,71.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:73.2,74.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:74.16,78.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:79.2,83.4 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:86.115,95.29 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:95.29,97.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:99.2,100.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:100.16,102.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:104.2,104.36 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:27.120,33.2 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:35.62,36.34 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:36.34,39.3 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:65.72,67.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:67.16,69.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:71.2,72.16 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:72.16,76.3 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:78.2,79.46 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:82.114,87.19 4 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:87.19,88.56 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:88.56,90.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:93.2,94.22 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:94.22,96.98 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:96.98,98.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:98.9,100.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:101.8,101.130 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:101.130,104.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:104.8,109.17 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:109.17,111.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:113.3,114.17 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:114.17,116.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:123.2,125.23 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:125.23,127.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:129.2,141.37 5 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:141.37,143.17 2 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:143.17,145.4 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:147.3,149.25 3 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:152.2,152.38 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:21.116,27.2 1 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:29.58,30.34 1 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:30.34,33.3 2 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:45.68,47.16 2 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:47.16,49.3 1 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:51.2,52.72 2 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:52.72,54.3 1 1 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:54.8,56.3 1 0 -github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:58.2,58.72 1 1 github.com/muety/wakapi/routes/api/activity.go:19.13,21.2 1 1 github.com/muety/wakapi/routes/api/activity.go:29.126,35.2 1 0 github.com/muety/wakapi/routes/api/activity.go:37.64,46.2 4 0 @@ -2263,6 +2057,207 @@ github.com/muety/wakapi/routes/api/summary.go:28.63,34.2 4 0 github.com/muety/wakapi/routes/api/summary.go:53.73,55.16 2 0 github.com/muety/wakapi/routes/api/summary.go:55.16,59.3 3 0 github.com/muety/wakapi/routes/api/summary.go:61.2,61.51 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:23.116,29.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:31.60,32.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:32.34,35.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:47.70,49.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:49.16,51.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:53.2,54.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:54.16,58.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:60.2,61.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:64.116,73.29 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:73.29,75.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:77.2,85.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:85.16,87.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/all_time.go:89.2,89.36 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:29.124,34.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:36.62,37.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:37.34,40.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:52.72,54.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:54.16,56.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:58.2,61.16 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:61.16,65.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:67.2,71.16 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:71.16,76.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/heartbeat.go:78.2,84.47 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:26.124,32.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:34.60,35.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:35.34,38.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:49.70,55.63 5 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:55.63,56.26 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:56.26,58.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:58.9,60.18 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:60.18,62.5 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:63.4,63.19 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:67.2,67.67 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:67.67,68.18 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:68.18,70.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:71.3,71.26 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:71.26,73.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:73.9,75.18 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:75.18,77.5 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:78.4,78.19 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:82.2,83.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:83.16,88.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:89.2,92.16 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:92.16,97.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:100.2,100.57 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:100.57,101.57 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:101.57,103.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:103.9,105.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:109.2,111.46 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:114.200,116.17 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:116.17,118.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:120.2,140.32 6 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:140.32,146.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:148.2,148.42 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:148.42,158.219 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:158.219,163.6 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/leaders.go:169.2,169.11 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:27.123,33.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:35.61,36.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:36.34,40.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:53.71,55.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:55.16,57.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:59.2,60.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:60.16,65.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:67.2,68.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:81.74,83.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:83.16,85.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:87.2,88.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:88.16,93.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:95.2,95.24 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:95.24,99.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:101.2,102.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:105.104,107.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:107.16,109.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:111.2,112.28 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:112.28,113.79 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:113.79,122.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/projects.go:125.2,125.22 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:23.112,29.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:31.58,32.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:32.34,42.3 5 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:63.68,69.53 5 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:69.53,71.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:73.2,74.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:74.16,78.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:82.2,82.22 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:82.22,83.100 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:83.100,85.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:85.9,87.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:90.2,91.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:91.16,95.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:97.2,99.69 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:99.69,103.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:105.2,106.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:106.16,110.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:112.2,118.68 6 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:118.68,120.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:120.34,122.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:123.3,123.36 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:123.36,125.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:126.3,126.35 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:126.35,128.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:129.3,129.30 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:129.30,131.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:132.3,132.35 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:132.35,134.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:137.2,137.49 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:140.136,149.16 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:149.16,151.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/stats.go:153.2,153.36 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:29.120,35.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:37.62,38.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:38.34,43.3 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:55.72,57.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:57.16,59.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:61.2,62.22 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:62.22,64.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:66.2,67.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:67.16,71.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:73.2,74.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:74.16,78.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:79.2,83.4 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:86.115,95.29 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:95.29,97.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:99.2,100.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:100.16,102.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/statusbar.go:104.2,104.36 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:27.120,33.2 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:35.62,36.34 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:36.34,39.3 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:65.72,67.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:67.16,69.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:71.2,72.16 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:72.16,76.3 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:78.2,79.46 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:82.114,87.19 4 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:87.19,88.56 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:88.56,90.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:93.2,94.22 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:94.22,96.98 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:96.98,98.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:98.9,100.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:101.8,101.130 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:101.130,104.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:104.8,109.17 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:109.17,111.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:113.3,114.17 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:114.17,116.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:123.2,125.23 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:125.23,127.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:129.2,141.37 5 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:141.37,143.17 2 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:143.17,145.4 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:147.3,149.25 3 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/summaries.go:152.2,152.38 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:21.116,27.2 1 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:29.58,30.34 1 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:30.34,33.3 2 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:45.68,47.16 2 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:47.16,49.3 1 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:51.2,52.72 2 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:52.72,54.3 1 1 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:54.8,56.3 1 0 +github.com/muety/wakapi/routes/compat/wakatime/v1/users.go:58.2,58.72 1 1 +github.com/muety/wakapi/routes/relay/relay.go:19.38,23.2 1 0 +github.com/muety/wakapi/routes/relay/relay.go:30.63,31.43 1 0 +github.com/muety/wakapi/routes/relay/relay.go:31.43,36.3 1 0 +github.com/muety/wakapi/routes/relay/relay.go:39.81,41.62 2 0 +github.com/muety/wakapi/routes/relay/relay.go:41.62,45.3 3 0 +github.com/muety/wakapi/routes/relay/relay.go:46.2,46.27 1 0 +github.com/muety/wakapi/routes/relay/relay.go:49.58,50.36 1 0 +github.com/muety/wakapi/routes/relay/relay.go:50.36,52.3 1 0 +github.com/muety/wakapi/routes/relay/relay.go:54.2,58.27 4 0 +github.com/muety/wakapi/routes/relay/relay.go:61.68,63.16 2 0 +github.com/muety/wakapi/routes/relay/relay.go:63.16,67.3 3 0 +github.com/muety/wakapi/routes/relay/relay.go:68.2,71.35 2 0 +github.com/muety/wakapi/routes/relay/relay.go:71.35,74.4 2 0 +github.com/muety/wakapi/routes/relay/relay.go:77.2,77.19 1 0 +github.com/muety/wakapi/routes/relay/relay.go:87.34,87.35 0 0 +github.com/muety/wakapi/routes/relay/relay.go:96.34,96.35 0 0 +github.com/muety/wakapi/routes/relay/relay.go:105.34,105.35 0 0 +github.com/muety/wakapi/routes/relay/relay.go:114.34,114.35 0 0 +github.com/muety/wakapi/routes/relay/relay.go:123.34,123.35 0 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:26.112,33.2 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:35.58,38.2 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:50.68,52.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:52.16,55.3 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:57.2,58.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:58.16,62.3 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:63.2,66.50 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:66.50,69.3 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:71.2,79.16 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:79.16,83.3 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:85.2,87.46 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:90.144,92.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:92.16,94.3 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:96.2,103.29 3 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:103.29,105.3 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:107.2,115.16 2 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:115.16,117.3 1 0 +github.com/muety/wakapi/routes/compat/shields/v1/badge.go:119.2,119.36 1 0 github.com/muety/wakapi/routes/handler.go:14.53,15.2 0 0 github.com/muety/wakapi/routes/handler.go:17.36,19.2 1 0 github.com/muety/wakapi/routes/home.go:29.112,35.2 1 1 @@ -2440,40 +2435,40 @@ github.com/muety/wakapi/routes/projects.go:58.2,67.16 5 0 github.com/muety/wakapi/routes/projects.go:67.16,76.3 2 0 github.com/muety/wakapi/routes/projects.go:78.2,87.49 2 0 github.com/muety/wakapi/routes/routes.go:18.13,20.2 1 0 -github.com/muety/wakapi/routes/routes.go:22.46,43.24 1 1 -github.com/muety/wakapi/routes/routes.go:43.24,45.4 1 0 -github.com/muety/wakapi/routes/routes.go:46.32,48.4 1 1 -github.com/muety/wakapi/routes/routes.go:49.31,51.4 1 1 -github.com/muety/wakapi/routes/routes.go:52.30,54.4 1 1 -github.com/muety/wakapi/routes/routes.go:55.47,57.4 1 0 -github.com/muety/wakapi/routes/routes.go:58.42,60.4 1 0 -github.com/muety/wakapi/routes/routes.go:61.42,63.4 1 0 -github.com/muety/wakapi/routes/routes.go:64.38,66.4 1 0 -github.com/muety/wakapi/routes/routes.go:67.39,69.4 1 0 -github.com/muety/wakapi/routes/routes.go:73.31,74.32 1 0 -github.com/muety/wakapi/routes/routes.go:74.32,76.3 1 0 -github.com/muety/wakapi/routes/routes.go:77.2,77.33 1 0 -github.com/muety/wakapi/routes/routes.go:77.33,79.3 1 0 -github.com/muety/wakapi/routes/routes.go:80.2,80.31 1 0 -github.com/muety/wakapi/routes/routes.go:80.31,82.3 1 0 -github.com/muety/wakapi/routes/routes.go:83.2,83.27 1 0 -github.com/muety/wakapi/routes/routes.go:83.27,85.3 1 0 -github.com/muety/wakapi/routes/routes.go:86.2,86.32 1 0 -github.com/muety/wakapi/routes/routes.go:86.32,88.3 1 0 -github.com/muety/wakapi/routes/routes.go:89.2,89.30 1 0 -github.com/muety/wakapi/routes/routes.go:89.30,91.3 1 0 -github.com/muety/wakapi/routes/routes.go:92.2,92.31 1 0 -github.com/muety/wakapi/routes/routes.go:92.31,94.3 1 0 -github.com/muety/wakapi/routes/routes.go:95.2,95.31 1 0 -github.com/muety/wakapi/routes/routes.go:95.31,97.3 1 0 -github.com/muety/wakapi/routes/routes.go:98.2,98.33 1 0 -github.com/muety/wakapi/routes/routes.go:98.33,100.3 1 0 -github.com/muety/wakapi/routes/routes.go:101.2,101.18 1 0 -github.com/muety/wakapi/routes/routes.go:104.22,107.86 2 1 -github.com/muety/wakapi/routes/routes.go:107.86,109.3 1 1 -github.com/muety/wakapi/routes/routes.go:109.8,110.13 1 0 -github.com/muety/wakapi/routes/routes.go:114.42,116.2 1 0 -github.com/muety/wakapi/routes/routes.go:118.24,120.2 1 0 +github.com/muety/wakapi/routes/routes.go:22.46,42.24 1 1 +github.com/muety/wakapi/routes/routes.go:42.24,44.4 1 0 +github.com/muety/wakapi/routes/routes.go:45.32,47.4 1 1 +github.com/muety/wakapi/routes/routes.go:48.31,50.4 1 1 +github.com/muety/wakapi/routes/routes.go:51.30,53.4 1 1 +github.com/muety/wakapi/routes/routes.go:54.47,56.4 1 0 +github.com/muety/wakapi/routes/routes.go:57.42,59.4 1 0 +github.com/muety/wakapi/routes/routes.go:60.42,62.4 1 0 +github.com/muety/wakapi/routes/routes.go:63.38,65.4 1 0 +github.com/muety/wakapi/routes/routes.go:66.39,68.4 1 0 +github.com/muety/wakapi/routes/routes.go:72.31,73.32 1 0 +github.com/muety/wakapi/routes/routes.go:73.32,75.3 1 0 +github.com/muety/wakapi/routes/routes.go:76.2,76.33 1 0 +github.com/muety/wakapi/routes/routes.go:76.33,78.3 1 0 +github.com/muety/wakapi/routes/routes.go:79.2,79.31 1 0 +github.com/muety/wakapi/routes/routes.go:79.31,81.3 1 0 +github.com/muety/wakapi/routes/routes.go:82.2,82.27 1 0 +github.com/muety/wakapi/routes/routes.go:82.27,84.3 1 0 +github.com/muety/wakapi/routes/routes.go:85.2,85.32 1 0 +github.com/muety/wakapi/routes/routes.go:85.32,87.3 1 0 +github.com/muety/wakapi/routes/routes.go:88.2,88.30 1 0 +github.com/muety/wakapi/routes/routes.go:88.30,90.3 1 0 +github.com/muety/wakapi/routes/routes.go:91.2,91.31 1 0 +github.com/muety/wakapi/routes/routes.go:91.31,93.3 1 0 +github.com/muety/wakapi/routes/routes.go:94.2,94.31 1 0 +github.com/muety/wakapi/routes/routes.go:94.31,96.3 1 0 +github.com/muety/wakapi/routes/routes.go:97.2,97.33 1 0 +github.com/muety/wakapi/routes/routes.go:97.33,99.3 1 0 +github.com/muety/wakapi/routes/routes.go:100.2,100.18 1 0 +github.com/muety/wakapi/routes/routes.go:103.22,106.86 2 1 +github.com/muety/wakapi/routes/routes.go:106.86,108.3 1 1 +github.com/muety/wakapi/routes/routes.go:108.8,109.13 1 0 +github.com/muety/wakapi/routes/routes.go:113.42,115.2 1 0 +github.com/muety/wakapi/routes/routes.go:117.24,119.2 1 0 github.com/muety/wakapi/routes/settings.go:70.20,85.2 1 0 github.com/muety/wakapi/routes/settings.go:87.61,98.2 5 0 github.com/muety/wakapi/routes/settings.go:100.76,101.22 1 0 @@ -2881,6 +2876,31 @@ github.com/muety/wakapi/routes/summary.go:137.37,139.17 2 0 github.com/muety/wakapi/routes/summary.go:139.17,141.4 1 0 github.com/muety/wakapi/routes/summary.go:142.3,142.44 1 0 github.com/muety/wakapi/routes/summary.go:144.2,144.23 1 0 +github.com/muety/wakapi/utils/fs/exists.go:10.37,12.16 2 0 +github.com/muety/wakapi/utils/fs/exists.go:12.16,13.13 1 0 +github.com/muety/wakapi/utils/fs/exists.go:16.2,19.3 1 0 +github.com/muety/wakapi/utils/fs/exists.go:28.56,31.2 2 0 +github.com/muety/wakapi/utils/fs/exists.go:33.46,34.18 1 0 +github.com/muety/wakapi/utils/fs/exists.go:34.18,35.44 1 0 +github.com/muety/wakapi/utils/fs/exists.go:35.44,37.4 1 0 +github.com/muety/wakapi/utils/fs/exists.go:39.2,41.18 3 0 +github.com/muety/wakapi/utils/fs/exists.go:41.18,43.3 1 0 +github.com/muety/wakapi/utils/fs/exists.go:44.2,44.15 1 0 +github.com/muety/wakapi/utils/fs/exists.go:47.56,49.2 1 0 +github.com/muety/wakapi/utils/fs/exists.go:58.48,63.2 1 0 +github.com/muety/wakapi/utils/fs/exists.go:65.51,66.34 1 0 +github.com/muety/wakapi/utils/fs/exists.go:66.34,68.3 1 0 +github.com/muety/wakapi/utils/fs/exists.go:69.2,69.35 1 0 +github.com/muety/wakapi/utils/fs/exists.go:72.63,74.2 1 0 +github.com/muety/wakapi/utils/fs/neutered.go:14.66,16.16 2 0 +github.com/muety/wakapi/utils/fs/neutered.go:16.16,18.3 1 0 +github.com/muety/wakapi/utils/fs/neutered.go:20.2,21.15 2 0 +github.com/muety/wakapi/utils/fs/neutered.go:21.15,23.47 2 0 +github.com/muety/wakapi/utils/fs/neutered.go:23.47,25.23 2 0 +github.com/muety/wakapi/utils/fs/neutered.go:25.23,27.5 1 0 +github.com/muety/wakapi/utils/fs/neutered.go:29.4,29.19 1 0 +github.com/muety/wakapi/utils/fs/neutered.go:33.2,33.15 1 0 +github.com/muety/wakapi/static/docs/docs.go:2007.13,2009.2 1 0 github.com/muety/wakapi/services/imports/wakatime.go:15.77,17.2 1 0 github.com/muety/wakapi/services/imports/wakatime.go:19.124,20.97 1 0 github.com/muety/wakapi/services/imports/wakatime.go:20.97,22.3 1 0 @@ -3021,31 +3041,6 @@ github.com/muety/wakapi/services/imports/wakatime_utils.go:105.9,110.4 1 0 github.com/muety/wakapi/services/imports/wakatime_utils.go:113.2,114.15 2 0 github.com/muety/wakapi/services/imports/wakatime_utils.go:114.15,119.3 1 0 github.com/muety/wakapi/services/imports/wakatime_utils.go:121.2,139.13 1 0 -github.com/muety/wakapi/utils/fs/exists.go:10.37,12.16 2 0 -github.com/muety/wakapi/utils/fs/exists.go:12.16,13.13 1 0 -github.com/muety/wakapi/utils/fs/exists.go:16.2,19.3 1 0 -github.com/muety/wakapi/utils/fs/exists.go:28.56,31.2 2 0 -github.com/muety/wakapi/utils/fs/exists.go:33.46,34.18 1 0 -github.com/muety/wakapi/utils/fs/exists.go:34.18,35.44 1 0 -github.com/muety/wakapi/utils/fs/exists.go:35.44,37.4 1 0 -github.com/muety/wakapi/utils/fs/exists.go:39.2,41.18 3 0 -github.com/muety/wakapi/utils/fs/exists.go:41.18,43.3 1 0 -github.com/muety/wakapi/utils/fs/exists.go:44.2,44.15 1 0 -github.com/muety/wakapi/utils/fs/exists.go:47.56,49.2 1 0 -github.com/muety/wakapi/utils/fs/exists.go:58.48,63.2 1 0 -github.com/muety/wakapi/utils/fs/exists.go:65.51,66.34 1 0 -github.com/muety/wakapi/utils/fs/exists.go:66.34,68.3 1 0 -github.com/muety/wakapi/utils/fs/exists.go:69.2,69.35 1 0 -github.com/muety/wakapi/utils/fs/exists.go:72.63,74.2 1 0 -github.com/muety/wakapi/utils/fs/neutered.go:14.66,16.16 2 0 -github.com/muety/wakapi/utils/fs/neutered.go:16.16,18.3 1 0 -github.com/muety/wakapi/utils/fs/neutered.go:20.2,21.15 2 0 -github.com/muety/wakapi/utils/fs/neutered.go:21.15,23.47 2 0 -github.com/muety/wakapi/utils/fs/neutered.go:23.47,25.23 2 0 -github.com/muety/wakapi/utils/fs/neutered.go:25.23,27.5 1 0 -github.com/muety/wakapi/utils/fs/neutered.go:29.4,29.19 1 0 -github.com/muety/wakapi/utils/fs/neutered.go:33.2,33.15 1 0 -github.com/muety/wakapi/static/docs/docs.go:2007.13,2009.2 1 0 github.com/muety/wakapi/utils/auth.go:15.79,17.54 2 0 github.com/muety/wakapi/utils/auth.go:17.54,19.3 1 0 github.com/muety/wakapi/utils/auth.go:21.2,23.16 3 0 @@ -3435,34 +3430,28 @@ github.com/muety/wakapi/services/alias.go:182.3,182.30 1 0 github.com/muety/wakapi/services/alias.go:183.8,185.3 1 0 github.com/muety/wakapi/services/diagnostics.go:14.101,19.2 1 0 github.com/muety/wakapi/services/diagnostics.go:21.101,24.2 2 0 -github.com/muety/wakapi/services/duration.go:16.78,22.2 2 1 -github.com/muety/wakapi/services/duration.go:24.123,28.16 3 1 -github.com/muety/wakapi/services/duration.go:28.16,30.3 1 0 -github.com/muety/wakapi/services/duration.go:38.2,43.31 4 1 -github.com/muety/wakapi/services/duration.go:43.31,46.62 2 1 -github.com/muety/wakapi/services/duration.go:46.62,48.4 1 1 -github.com/muety/wakapi/services/duration.go:50.3,50.20 1 1 -github.com/muety/wakapi/services/duration.go:50.20,52.12 2 1 -github.com/muety/wakapi/services/duration.go:55.3,65.15 3 1 -github.com/muety/wakapi/services/duration.go:65.15,67.4 1 0 -github.com/muety/wakapi/services/duration.go:68.3,74.79 2 1 -github.com/muety/wakapi/services/duration.go:74.79,76.41 2 1 -github.com/muety/wakapi/services/duration.go:76.41,78.5 1 1 -github.com/muety/wakapi/services/duration.go:79.4,79.15 1 1 -github.com/muety/wakapi/services/duration.go:80.9,82.4 1 1 -github.com/muety/wakapi/services/duration.go:84.3,84.10 1 1 -github.com/muety/wakapi/services/duration.go:87.2,89.31 2 1 -github.com/muety/wakapi/services/duration.go:89.31,90.26 1 1 -github.com/muety/wakapi/services/duration.go:90.26,95.51 1 1 -github.com/muety/wakapi/services/duration.go:95.51,96.13 1 1 -github.com/muety/wakapi/services/duration.go:99.4,99.54 1 1 -github.com/muety/wakapi/services/duration.go:99.54,100.13 1 0 -github.com/muety/wakapi/services/duration.go:107.4,107.23 1 1 -github.com/muety/wakapi/services/duration.go:107.23,109.5 1 1 -github.com/muety/wakapi/services/duration.go:110.4,110.36 1 1 -github.com/muety/wakapi/services/duration.go:114.2,114.49 1 1 -github.com/muety/wakapi/services/duration.go:114.49,116.3 1 1 -github.com/muety/wakapi/services/duration.go:118.2,118.32 1 1 +github.com/muety/wakapi/services/duration.go:18.78,24.2 2 1 +github.com/muety/wakapi/services/duration.go:26.123,30.16 3 1 +github.com/muety/wakapi/services/duration.go:30.16,32.3 1 0 +github.com/muety/wakapi/services/duration.go:40.2,45.31 4 1 +github.com/muety/wakapi/services/duration.go:45.31,49.62 2 1 +github.com/muety/wakapi/services/duration.go:49.62,51.4 1 1 +github.com/muety/wakapi/services/duration.go:54.3,54.20 1 1 +github.com/muety/wakapi/services/duration.go:54.20,57.12 3 1 +github.com/muety/wakapi/services/duration.go:63.3,71.79 4 1 +github.com/muety/wakapi/services/duration.go:71.79,74.4 2 1 +github.com/muety/wakapi/services/duration.go:74.9,76.4 1 1 +github.com/muety/wakapi/services/duration.go:78.3,78.10 1 1 +github.com/muety/wakapi/services/duration.go:81.2,83.31 2 1 +github.com/muety/wakapi/services/duration.go:83.31,84.26 1 1 +github.com/muety/wakapi/services/duration.go:84.26,89.51 1 1 +github.com/muety/wakapi/services/duration.go:89.51,90.13 1 1 +github.com/muety/wakapi/services/duration.go:92.4,92.54 1 1 +github.com/muety/wakapi/services/duration.go:92.54,93.13 1 0 +github.com/muety/wakapi/services/duration.go:96.4,96.36 1 1 +github.com/muety/wakapi/services/duration.go:100.2,100.49 1 1 +github.com/muety/wakapi/services/duration.go:100.49,102.3 1 1 +github.com/muety/wakapi/services/duration.go:104.2,104.32 1 1 github.com/muety/wakapi/services/heartbeat.go:29.141,43.33 3 0 github.com/muety/wakapi/services/heartbeat.go:43.33,44.31 1 0 github.com/muety/wakapi/services/heartbeat.go:44.31,49.4 4 0 diff --git a/models/user.go b/models/user.go index afa3a53..1d5a499 100644 --- a/models/user.go +++ b/models/user.go @@ -12,9 +12,10 @@ import ( ) const ( - DefaultHeartbeatsTimeout = 2 * time.Minute - MinHeartbeatsTimeout = 30 * time.Second - MaxHeartbeatsTimeout = 5 * time.Minute + DefaultHeartbeatsTimeout = 10 * time.Minute + DefaultHeartbeatsTimeoutLegacy = 2 * time.Minute + MinHeartbeatsTimeout = 1 * time.Minute + MaxHeartbeatsTimeout = 1 * time.Hour ) func init() { @@ -49,7 +50,7 @@ type User struct { StripeCustomerId string `json:"-"` InvitedBy string `json:"-"` ExcludeUnknownProjects bool `json:"-"` - HeartbeatsTimeoutSec int `json:"-" gorm:"default:120"` // https://github.com/muety/wakapi/issues/156 + HeartbeatsTimeoutSec int `json:"-" gorm:"default:600"` // https://github.com/muety/wakapi/issues/156 } type Login struct { diff --git a/repositories/heartbeat.go b/repositories/heartbeat.go index 75c54eb..3d80510 100644 --- a/repositories/heartbeat.go +++ b/repositories/heartbeat.go @@ -33,7 +33,6 @@ func (r *HeartbeatRepository) GetAll() ([]*models.Heartbeat, error) { } func (r *HeartbeatRepository) InsertBatch(heartbeats []*models.Heartbeat) error { - // sqlserver on conflict has bug https://github.com/go-gorm/sqlserver/issues/100 // As a workaround, insert one by one, and ignore duplicate key error if r.db.Dialector.Name() == (sqlserver.Dialector{}).Name() { diff --git a/routes/settings.go b/routes/settings.go index 1c5e962..4ba7cd3 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -376,10 +376,11 @@ func (h *SettingsHandler) actionUpdateHeartbeatsTimeout(w http.ResponseWriter, r defer h.userSrvc.FlushCache() val, err := strconv.ParseInt(r.PostFormValue("heartbeats_timeout"), 0, 0) - if dur := time.Duration(val) * time.Second; err != nil || dur < models.MinHeartbeatsTimeout || dur > models.MaxHeartbeatsTimeout { + dur := time.Duration(val) * time.Minute + if err != nil || dur < models.MinHeartbeatsTimeout || dur > models.MaxHeartbeatsTimeout { return actionResult{http.StatusBadRequest, "", "invalid input", nil} } - user.HeartbeatsTimeoutSec = int(val) + user.HeartbeatsTimeoutSec = int(dur.Seconds()) if _, err := h.userSrvc.Update(user); err != nil { return actionResult{http.StatusInternalServerError, "", "internal sever error", nil} diff --git a/scripts/aggregate_durations_mysql.sql b/scripts/aggregate_durations_mysql.sql index e1a1b2a..b7a8e57 100644 --- a/scripts/aggregate_durations_mysql.sql +++ b/scripts/aggregate_durations_mysql.sql @@ -1,9 +1,13 @@ -SELECT project, language, editor, operating_system, machine, branch, SUM(GREATEST(1, diff)) as 'sum' -FROM ( - SELECT project, language, editor, operating_system, machine, branch, TIME_TO_SEC(LEAST(TIMEDIFF(time, LAG(time) over w), '00:02:00')) as 'diff' - FROM heartbeats - WHERE user_id = 'n1try' - WINDOW w AS (ORDER BY time) - ) s2 +SELECT project, language, editor, operating_system, machine, branch, SUM(diff) as 'sum' +FROM (SELECT project, + language, + editor, + operating_system, + machine, + branch, + TIME_TO_SEC(LEAST(TIMEDIFF(time, LAG(time) over w), '00:00:00')) as 'diff' -- time constant ~ heartbeats padding (none by default, formerly 2 mins) + FROM heartbeats + WHERE user_id = 'n1try' + WINDOW w AS (ORDER BY time)) s2 WHERE diff IS NOT NULL GROUP BY project, language, editor, operating_system, machine, branch; \ No newline at end of file diff --git a/scripts/aggregate_durations_postgres.sql b/scripts/aggregate_durations_postgres.sql index 96db0f7..efd815c 100644 --- a/scripts/aggregate_durations_postgres.sql +++ b/scripts/aggregate_durations_postgres.sql @@ -1,9 +1,14 @@ -SELECT project, language, editor, operating_system, machine, branch, SUM(GREATEST(1, diff)) as 'sum' -FROM ( - SELECT project, language, editor, operating_system, machine, branch, EXTRACT(EPOCH FROM LEAST(time - LAG(time) OVER w, INTERVAL '2 minutes')) as diff - FROM heartbeats - WHERE user_id = 'n1try' - WINDOW w AS (ORDER BY time) - ) s2 +SELECT project, language, editor, operating_system, machine, branch, SUM(diff) as sum +FROM (SELECT project, + language, + editor, + operating_system, + machine, + branch, + EXTRACT(EPOCH FROM + LEAST(time - LAG(time) OVER w, INTERVAL '0 minutes')) as diff -- time constant ~ heartbeats padding (none by default, formerly 2 mins) + FROM heartbeats + WHERE user_id = 'n1try' + WINDOW w AS (ORDER BY time)) s2 WHERE diff IS NOT NULL GROUP BY project, language, editor, operating_system, machine, branch; \ No newline at end of file diff --git a/services/duration.go b/services/duration.go index 4d49d37..1b00128 100644 --- a/services/duration.go +++ b/services/duration.go @@ -1,13 +1,15 @@ package services import ( + "github.com/duke-git/lancet/v2/condition" "github.com/duke-git/lancet/v2/datetime" - "github.com/duke-git/lancet/v2/mathutil" "github.com/muety/wakapi/config" "github.com/muety/wakapi/models" "time" ) +const heartbeatPadding = 0 * time.Second + type DurationService struct { config *config.Config heartbeatService IHeartbeatService @@ -30,11 +32,11 @@ func (srv *DurationService) Get(from, to time.Time, user *models.User, filters * } // Aggregation - // the below logic is approximately equivalent to the SQL query at scripts/aggregate_durations_mysql.sql - // a postgres-compatible script was contributed by @cwilby and is available at scripts/aggregate_durations_postgres.sql - // i'm hesitant to replicate that logic for sqlite and mssql too (because probably painful to impossible), but we could - // think about adding a distrinctio here to use pure-sql aggregation for mysql and postgres, and traditional, programmatic - // aggregation for all other databases + // The below logic is approximately (no filtering, no "same day"-check) equivalent to the SQL query at scripts/aggregate_durations_mysql.sql. + // A Postgres-compatible script was contributed by @cwilby and is available at scripts/aggregate_durations_postgres.sql + // I'm hesitant to replicate that logic for sqlite and mssql too (because probably painful to impossible), but we could + // think about adding a distinction here to use pure-sql aggregation for MySQL and Postgres, and traditional, programmatic + // aggregation for all other databases. var count int var latest *models.Duration @@ -43,39 +45,31 @@ func (srv *DurationService) Get(from, to time.Time, user *models.User, filters * for _, h := range heartbeats { d1 := models.NewDurationFromHeartbeat(h).WithEntityIgnored().Hashed() + // initialize map entry if list, ok := mapping[d1.GroupHash]; !ok || len(list) < 1 { - mapping[d1.GroupHash] = []*models.Duration{d1} + mapping[d1.GroupHash] = []*models.Duration{} } + // first heartbeat if latest == nil { + mapping[d1.GroupHash] = append(mapping[d1.GroupHash], d1) latest = d1 continue } + // Skip heartbeats that span across two adjacent summaries (assuming there are no more than 1 summary per day). + // This is relevant to prevent the time difference between generating summaries from raw heartbeats and aggregating pre-generated summaries. + // For the latter case, the very last heartbeat of a day won't be counted, so we don't want to count it here either sameDay := datetime.BeginOfDay(d1.Time.T()) == datetime.BeginOfDay(latest.Time.T()) - dur := time.Duration(mathutil.Min( - int64(d1.Time.T().Sub(latest.Time.T().Add(latest.Duration))), - int64(heartbeatsTimeout), - )) + dur := condition.Ternary[bool, time.Duration](sameDay, d1.Time.T().Sub(latest.Time.T().Add(latest.Duration)), 0) + latest.Duration += condition.Ternary[bool, time.Duration](dur < heartbeatsTimeout, dur, heartbeatPadding) - // skip heartbeats that span across two adjacent summaries (assuming there are no more than 1 summary per day) - // this is relevant to prevent the time difference between generating summaries from raw heartbeats and aggregating pre-generated summaries - // for the latter case, the very last heartbeat of a day won't be counted, so we don't want to count it here either - // another option would be to adapt the Summarize() method to always append up to DefaultHeartbeatsTimeout seconds to a day's very last duration - if !sameDay { - dur = 0 - } - latest.Duration += dur - - // start new "group" if: - // (a) heartbeats were too far apart each other, - // (b) if they are of a different entity or, - // (c) if they span across two days + // Start new "group" if: + // (a) heartbeats were too far apart each other or, + // (b) they are of a different entity or, + // (c) they span across two days if dur >= heartbeatsTimeout || latest.GroupHash != d1.GroupHash || !sameDay { - list := mapping[d1.GroupHash] - if d0 := list[len(list)-1]; d0 != d1 { - mapping[d1.GroupHash] = append(mapping[d1.GroupHash], d1) - } + mapping[d1.GroupHash] = append(mapping[d1.GroupHash], d1) latest = d1 } else { latest.NumHeartbeats++ @@ -88,31 +82,23 @@ func (srv *DurationService) Get(from, to time.Time, user *models.User, filters * for _, list := range mapping { for _, d := range list { - // even when filters are applied, we'll still have to compute the whole summary first and then filter out non-matching durations - // if we fetched only matching heartbeats in the first place, there will be false positive gaps (see DefaultHeartbeatsTimeout) - // in case the user worked on different projects in parallel - // see https://github.com/muety/wakapi/issues/535 + // Even when filters are applied, we'll still have to compute the whole summary first and then filter out non-matching durations. + // If we fetched only matching heartbeats in the first place, there will be false positive gaps (see heartbeatsTimeout) + // in case the user worked on different projects in parallel. + // See https://github.com/muety/wakapi/issues/535, https://github.com/muety/wakapi/issues/716 if filters != nil && !filters.MatchDuration(d) { continue } - if user.ExcludeUnknownProjects && d.Project == "" { continue } - // will only happen if two heartbeats with different hashes (e.g. different project) have the same timestamp - // that, in turn, will most likely only happen for mysql, where `time` column's precision was set to second for a while - // assume that two non-identical heartbeats with identical time are sub-second apart from each other, so round up to expectancy value - // also see https://github.com/muety/wakapi/issues/340 - if d.Duration == 0 { - d.Duration = 500 * time.Millisecond - } durations = append(durations, d) } } if len(heartbeats) == 1 && len(durations) == 1 { - durations[0].Duration = heartbeatsTimeout + durations[0].Duration = heartbeatPadding } return durations.Sorted(), nil diff --git a/services/duration_test.go b/services/duration_test.go index a3b15e6..efe8b84 100644 --- a/services/duration_test.go +++ b/services/duration_test.go @@ -45,7 +45,7 @@ type DurationServiceTestSuite struct { } func (suite *DurationServiceTestSuite) SetupSuite() { - suite.TestUser = &models.User{ID: TestUserId} + suite.TestUser = &models.User{ID: TestUserId, HeartbeatsTimeoutSec: int(models.DefaultHeartbeatsTimeoutLegacy / time.Second)} // https://anchr.io/i/F0HEK.jpg suite.TestStartTime = time.Unix(0, MinUnixTime1) @@ -160,7 +160,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get() { assert.Nil(suite.T(), err) assert.Len(suite.T(), durations, 1) - assert.Equal(suite.T(), models.DefaultHeartbeatsTimeout, durations.First().Duration) + assert.Equal(suite.T(), time.Duration(0), durations.First().Duration) assert.Equal(suite.T(), 1, durations.First().NumHeartbeats) /* TEST 3 */ @@ -171,7 +171,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get() { assert.Nil(suite.T(), err) assert.Len(suite.T(), durations, 3) - assert.Equal(suite.T(), 150*time.Second, durations[0].Duration) + assert.Equal(suite.T(), 30*time.Second, durations[0].Duration) assert.Equal(suite.T(), 20*time.Second, durations[1].Duration) assert.Equal(suite.T(), 15*time.Second, durations[2].Duration) assert.Equal(suite.T(), TestEditorGoland, durations[0].Editor) @@ -198,6 +198,8 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get_Filtered() { durations, err = sut.Get(from, to, suite.TestUser, models.NewFiltersWith(models.SummaryEditor, TestEditorGoland)) assert.Nil(suite.T(), err) assert.Len(suite.T(), durations, 2) + assert.Equal(suite.T(), 30*time.Second, durations[0].Duration) + assert.Equal(suite.T(), 20*time.Second, durations[1].Duration) for _, d := range durations { assert.Equal(suite.T(), TestEditorGoland, d.Editor) } @@ -213,7 +215,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get_CustomTimeout() { ) defer func() { - suite.TestUser.HeartbeatsTimeoutSec = int(models.DefaultHeartbeatsTimeout / time.Second) // revert to defaults + suite.TestUser.HeartbeatsTimeoutSec = int(models.DefaultHeartbeatsTimeoutLegacy / time.Second) // revert to defaults }() from, to = suite.TestStartTime, suite.TestStartTime.Add(1*time.Hour) @@ -224,7 +226,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get_CustomTimeout() { durations, _ = sut.Get(from, to, suite.TestUser, nil) assert.Len(suite.T(), durations, 3) - assert.Equal(suite.T(), 90*time.Second, durations[0].Duration) + assert.Equal(suite.T(), 30*time.Second, durations[0].Duration) assert.Equal(suite.T(), 20*time.Second, durations[1].Duration) assert.Equal(suite.T(), 15*time.Second, durations[2].Duration) assert.Equal(suite.T(), 3, durations[0].NumHeartbeats) @@ -236,7 +238,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get_CustomTimeout() { durations, _ = sut.Get(from, to, suite.TestUser, nil) assert.Len(suite.T(), durations, 3) - assert.Equal(suite.T(), 160*time.Second, durations[0].Duration) + assert.Equal(suite.T(), 30*time.Second, durations[0].Duration) assert.Equal(suite.T(), 20*time.Second, durations[1].Duration) assert.Equal(suite.T(), 15*time.Second, durations[2].Duration) assert.Equal(suite.T(), 3, durations[0].NumHeartbeats) @@ -244,7 +246,7 @@ func (suite *DurationServiceTestSuite) TestDurationService_Get_CustomTimeout() { assert.Equal(suite.T(), 3, durations[2].NumHeartbeats) /* Test 3 */ - suite.TestUser.HeartbeatsTimeoutSec = 300 + suite.TestUser.HeartbeatsTimeoutSec = 140 durations, _ = sut.Get(from, to, suite.TestUser, nil) assert.Len(suite.T(), durations, 2) diff --git a/views/settings.tpl.html b/views/settings.tpl.html index b7cebd8..930e9fa 100644 --- a/views/settings.tpl.html +++ b/views/settings.tpl.html @@ -466,8 +466,8 @@
- - (min. 30 seconds, max. 5 minutes) + + (min. 1 min, max. 60 min)