module VideoDataAnalyzer def get_top_substances(limit = 10) substance_counts = Hash.new(0) @data.each { |entry| substance_counts[entry[:substance]] += 1 } substance_counts.sort_by { |_, count| -count }.take(limit) end def get_one_time_substances substance_counts = Hash.new(0) @data.each { |entry| substance_counts[entry[:substance]] += 1 } substance_counts.select { |_, count| count == 1 }.keys.sort end def get_peak_month monthly = Hash.new(0) @data.each do |entry| month_key = entry[:timestamp].strftime('%Y-%m') monthly[month_key] += 1 end monthly.max_by { |_, count| count } end def get_time_of_day_analysis periods = { 'Morning (6-11)' => (6..11), 'Afternoon (12-17)' => (12..17), 'Evening (18-23)' => (18..23), 'Night (0-5)' => (0..5) } analysis = {} periods.each { |period, _| analysis[period] = 0 } @data.each do |entry| hour = entry[:timestamp].hour period = periods.find { |_, range| range.include?(hour) }&.first analysis[period] += 1 if period end analysis end def get_hardest_day daily_counts = Hash.new(0) @data.each do |entry| date = entry[:timestamp].to_date daily_counts[date] += 1 end return nil if daily_counts.empty? daily_counts.max_by { |_, count| count } end def get_streak_analysis past_data = @data.select { |entry| entry[:timestamp].to_date <= Date.today - 1 } return {} if past_data.empty? substance_dates = {} past_data.each do |entry| substance = entry[:substance] date = entry[:timestamp].to_date substance_dates[substance] ||= [] substance_dates[substance] << date unless substance_dates[substance].include?(date) end streaks = {} substance_dates.each do |substance, dates| dates.sort! current_streak = 1 max_streak = 1 (1...dates.length).each do |i| if dates[i] == dates[i-1] + 1 current_streak += 1 max_streak = [max_streak, current_streak].max else current_streak = 1 end end streaks[substance] = max_streak if max_streak > 1 end streaks end def get_route_analysis routes = Hash.new { |h, k| h[k] = [] } @data.each do |entry| routes[entry[:substance]] << entry[:route] end routes end def get_peak_time_period(time_analysis) peak_period, peak_count = time_analysis.max_by { |_, count| count } { period: peak_period.split(' ')[0], # Just the time name count: peak_count } end def format_time_bars(time_analysis) max_count = time_analysis.values.max time_analysis.map do |period, count| percentage = max_count > 0 ? (count.to_f / max_count) * 100 : 0 { label: period.split(' ')[0], value: "#{count} uses", percentage: percentage } end end def format_month_name(month_string) Date.strptime(month_string, '%Y-%m').strftime('%B') end def get_surprise_stat return nil if @data.empty? # Calculate various interesting statistics stats = [] # Unique dates unique_dates = @data.map { |e| e[:timestamp].to_date }.uniq.count if unique_dates > 0 stats << { title: "#{unique_dates} Different Days", subtitle: "of documented experiences", value: "#{unique_dates} days", flavor: "Spreading the joy around" } end # Weekend vs weekday usage weekend_count = @data.count { |e| [0, 6].include?(e[:timestamp].wday) } weekday_count = @data.count - weekend_count if weekend_count > weekday_count stats << { title: "Weekend Warrior", subtitle: "#{weekend_count} weekend experiences", value: "#{((weekend_count.to_f / @data.length) * 100).round(1)}%", flavor: "Saturday night's alright" } elsif weekday_count > weekend_count * 2 stats << { title: "Weekday Rebel", subtitle: "#{weekday_count} weekday experiences", value: "#{((weekday_count.to_f / @data.length) * 100).round(1)}%", flavor: "Monday motivation" } end # Most common dose if numeric doses = @data.map { |e| e[:dose] }.compact numeric_doses = doses.select { |d| d.to_s.match(/^\d+\.?\d*$/) }.map(&:to_f) if numeric_doses.any? avg_dose = (numeric_doses.sum / numeric_doses.length).round(2) stats << { title: "Average Dose", subtitle: "when measurable", value: "#{avg_dose}", flavor: "Consistency is key" } end # Most active season seasons = { 'Winter' => 0, 'Spring' => 0, 'Summer' => 0, 'Fall' => 0 } @data.each do |entry| month = entry[:timestamp].month season = case month when 12, 1, 2 then 'Winter' when 3, 4, 5 then 'Spring' when 6, 7, 8 then 'Summer' when 9, 10, 11 then 'Fall' end seasons[season] += 1 end peak_season, peak_count = seasons.max_by { |_, count| count } if peak_count > 0 stats << { title: "#{peak_season} Person", subtitle: "#{peak_count} experiences in #{peak_season.downcase}", value: "#{((peak_count.to_f / @data.length) * 100).round(1)}%", flavor: "Seasonal affective enhancement" } end # Return random stat or nil stats.sample end def get_top_substances_subtitle(top_substances) return "No substances found" if top_substances.empty? top_name, top_count = top_substances.first total_uses = @data.length percentage = ((top_count.to_f / total_uses) * 100).round(1) "#{top_name} dominated with #{percentage}% of your usage" end end