mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-20 00:35:22 +00:00
Fixed (FINALLY!!)
This commit is contained in:
parent
bfaa18aa56
commit
ddc25d1cfe
3 changed files with 28 additions and 56 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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|
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue