Fixed (FINALLY!!)

This commit is contained in:
Mahad Kalam 2026-02-10 02:31:35 +00:00
parent bfaa18aa56
commit ddc25d1cfe
3 changed files with 28 additions and 56 deletions

View file

@ -156,65 +156,34 @@ class Api::Hackatime::V1::HackatimeController < ApplicationController
end
def calculate_category_stats(heartbeats, category)
return [] if heartbeats.empty?
durations = heartbeats.group(category).duration_seconds
# Manual calculation approach to avoid SQL issues
category_durations = {}
# First, group heartbeats by category
grouped_heartbeats = {}
heartbeats.each do |hb|
category_value = hb.send(category) || "unknown"
grouped_heartbeats[category_value] ||= []
grouped_heartbeats[category_value] << hb
end
# Calculate duration for each category
grouped_heartbeats.each do |name, hbs|
duration = 0
hbs = hbs.sort_by(&:time)
prev_time = nil
hbs.each do |hb|
current_time = hb.time
if prev_time && (current_time - prev_time) <= 120 # 2-minute timeout
duration += (current_time - prev_time)
end
prev_time = current_time
end
# Add a final 2 minutes for the last heartbeat if we have any
duration += 120 if hbs.any?
category_durations[name] = duration
end
# Calculate total duration for percentage calculations
total_duration = category_durations.values.sum.to_f
total_duration = durations.values.sum.to_f
return [] if total_duration == 0
# Format the data for each category
category_durations.map do |name, duration|
name = name.presence || "unknown"
name = case category
when "editor" then ApplicationController.helpers.display_editor_name(name)
when "operating_system" then ApplicationController.helpers.display_os_name(name)
when "language" then ApplicationController.helpers.display_language_name(name)
else name
h = ApplicationController.helpers
durations.filter_map do |name, duration|
next if duration <= 0
display_name = (name.presence || "unknown")
display_name = case category
when "editor" then h.display_editor_name(display_name)
when "operating_system" then h.display_os_name(display_name)
when "language" then h.display_language_name(display_name)
else display_name
end
percent = ((duration / total_duration) * 100).round(2)
hours = duration.to_i / 3600
minutes = (duration.to_i % 3600) / 60
seconds = duration.to_i % 60
digital = format("%d:%02d:%02d", hours, minutes, seconds)
text = "#{hours} hrs #{minutes} mins"
hours = duration / 3600
minutes = (duration % 3600) / 60
seconds = duration % 60
{
name: name,
total_seconds: duration.to_i,
name: display_name,
total_seconds: duration,
percent: percent,
digital: digital,
text: text,
digital: format("%d:%02d:%02d", hours, minutes, seconds),
text: "#{hours} hrs #{minutes} mins",
hours: hours,
minutes: minutes,
seconds: seconds

View file

@ -84,18 +84,22 @@ class StaticPagesController < InertiaController
key += "_#{params[:from]}_#{params[:to]}" if params[:interval] == "custom"
key += "_archived" if archived
durations = Rails.cache.fetch(key, expires_in: 1.minute) do
cached = Rails.cache.fetch(key, expires_in: 1.minute) do
hb = current_user.heartbeats.filter_by_time_range(params[:interval], params[:from], params[:to])
labels = current_user.project_labels
hb.group(:project).duration_seconds.filter_map do |proj, dur|
projects = hb.group(:project).duration_seconds.filter_map do |proj, dur|
next if dur <= 0
m = @project_repo_mappings.find { |p| p.project_name == proj }
{ project: labels.find { |p| p.project_key == proj }&.label || proj || "Unknown",
project_key: proj, repo_url: m&.repo_url, repository: m&.repository,
has_mapping: m.present?, duration: dur }
end.sort_by { |p| -p[:duration] }
{ projects: projects, total_time: hb.duration_seconds }
end
durations = cached[:projects]
total_time = cached[:total_time]
durations = durations.select { |p| archived_names.include?(p[:project_key]) == archived }
durations = durations.map do |p|
@ -103,7 +107,7 @@ class StaticPagesController < InertiaController
p.merge(repo_url: m&.repo_url, repository: m&.repository)
end
render partial: "project_durations", locals: { project_durations: durations, show_archived: archived }
render partial: "project_durations", locals: { project_durations: durations, total_time: total_time, show_archived: archived }
end
def currently_hacking
@ -233,7 +237,7 @@ class StaticPagesController < InertiaController
end
hb = hb.filter_by_time_range(interval, params[:from], params[:to])
result[:total_time] = hb.group(:project).duration_seconds.values.sum
result[:total_time] = hb.duration_seconds
result[:total_heartbeats] = hb.count
filters.each do |f|

View file

@ -1,7 +1,6 @@
<%= turbo_frame_tag "project_durations" do %>
<% max = project_durations.map { |p| p[:duration] }.max || 1 %>
<p class="text-lg text-white mt-6">
<% total_time = project_durations.sum { |p| p[:duration].to_i } %>
<% if total_time > 0 %>
You've spent <span class="font-semibold"><%= short_time_detailed(total_time) %></span> coding across all projects.