Skip to content

Instantly share code, notes, and snippets.

@botanicus
Created May 29, 2019 14:54
Show Gist options
  • Save botanicus/d465a81dcb9a57250b9cce5178aac46e to your computer and use it in GitHub Desktop.
Save botanicus/d465a81dcb9a57250b9cce5178aac46e to your computer and use it in GitHub Desktop.
#!/bin/zsh
play() {
while true; do
echo "~ Playing $1."
afplay ~/"Dropbox/Media/Meditation/Lifeflow/LifeFlow 2.0 Bonus/$1"
done
}
case "$1" in
learn)
play "02 LifeFlow - Optimal Learning.mp3" ;;
work)
play "03 LifeFlow 2.0 - Creative Flow.mp3" ;;
awaken)
play "01 LifeFlow - Awaken.mp3" ;;
nirvana)
play "04 LifeFlow 2.0 - Nirvana" ;;
*)
echo "Usage: $0 [learn|work|awaken|nirvana]" ;;
esac
#!/usr/bin/env ruby
require 'yaml'
require 'find'
require 'refined-refinements/colours'
PATH = File.expand_path('~/Dropbox/Data/Data/Headspace.yml')
using RR::ColourExts
def play(data, next_episode_files)
next_episode_files.each do |path|
puts "~ #{path}"
system("afplay '#{path}'")
end
today_episode_number = next_episode_files.first.match(/Day (\d+)/)[1]
series = next_episode_files.first.split('/')[-3..-2].join('/')
episode_path = "#{series}/Day #{today_episode_number}"
data[:episodes][episode_path] = Time.now
if File.size(PATH) < data.to_yaml.length
File.open(PATH, 'w') do |file|
file.puts(data.to_yaml)
end
else
puts "\n\n<red>ERROR:</red> The data we were to write are of a smaller size than the original size. Aborting.\n\n".colourise
puts "<bright_black>#{data.to_yaml}</bright_black>".colourise
end
rescue Interrupt
puts ''
end
def play_first_episode(data, series)
next_episode_files = Dir.glob("#{File.expand_path("#{data[:base_dir]}/#{series}")}/*Day 1 *")
play(data, next_episode_files)
end
def play_next(data)
if next_episode_files = find_next_episode_files(data)
play(data, next_episode_files)
else
abort "No episodes played yet."
end
end
def find_next_episode_files(data)
episodes = data[:episodes] || Hash.new
if last_episode = episodes.keys.last
last_episode_day = last_episode.split('/').last.match('Day (\d+)')[1]
today_episode_number = last_episode_day.to_i + 1
Dir.glob("#{File.dirname(last_episode)}/*Day*").select do |path|
# Protection against matching 30 if the day is 3.
path.match(/Day #{today_episode_number}\b/)
end
end
end
def list_series
directories = Array.new
Find.find('.') do |path|
if File.directory?(path) && path.split('/').length == 3
directories << path[2..-1]
end
end
directories.uniq.group_by { |path| path.split('/').first }.each do |group, dirs|
puts "<green>#{group}</green>".colourise
dirs.each do |dir|
puts " #{group}/<magenta>#{dir.split('/').last}</magenta>".colourise
end
puts
end
end
def show_next_episode(data)
if next_episode_path = find_next_episode_files(data).first
dir, basename = File.split(next_episode_path)
puts "#{dir}/#{basename.match(/Day \d+/)[0]}"
else
exit 1
end
end
####
data = begin
YAML.load_file(File.expand_path('~/Dropbox/Data/Data/Headspace.yml'))
rescue Errno::ENOENT
abort "Write ~/Dropbox/Data/Data/Headspace.yml."
end
Dir.chdir(File.expand_path(data[:base_dir]))
case ARGV.shift
when 'play' then play_next(data)
when 'next?' then show_next_episode(data)
when 'series' then list_series
when 'start' then play_first_episode(data, ARGV.shift)
else
abort DATA.read.colourise
end
__END__
headspace play <bright_black># Start the next episode.</bright_black>
headspace next?
headspace start "Health Series/3 - Stress"
headspace series
#!/usr/bin/env ruby
require 'yaml'
require 'timeout'
require 'refined-refinements/hour'
require 'refined-refinements/colours'
require 'refined-refinements/homepath'
# 20 days, 1 hour a day.
TIME_MEDITATED_PER_RECORDING = Hour.new(10) # 20
using RR::ColouredTerminal
PATH = RR::Homepath.new('~/Dropbox/Data/Data/LifeFlow.yml')
data = begin
hash = YAML.load_file(PATH.expand)
hash = hash.reduce(Hash.new) do |buffer, (key, values)|
buffer.merge(key =>
values.reduce(Hash.new) { |b, (time, duration)|
b.merge(time => Hour.parse(duration))
})
end
hash.default_proc = Proc.new { |hash, key| hash[key] = Hash.new }
hash
rescue Errno::ENOENT
Hash.new { |hash, key| hash[key] = Array.new }
end
def base_dir
File.expand_path("~/Dropbox/Media/Meditation/Lifeflow")
end
def recordings
Dir.glob("#{base_dir}/*.mp3").sort[1..-1].map(&File.method(:basename))
end
def find_recording(data, index = 0)
recording = recordings[index]
time_meditated_per_recording = data[recording].values.reduce(:+) || Hour.new(0)
unless time_meditated_per_recording >= TIME_MEDITATED_PER_RECORDING
recording
else
find_recording(data, index + 1)
end
end
def timeout_maybe(timeout, &block)
timeout ? Timeout.timeout(timeout * 60, &block) : block.call
end
def play(path)
path = RR::Homepath.new(path)
puts "<bold>~</bold> <green>Playing</green> #{path}"
timeout_maybe(ARGV.first && ARGV.shift.to_i) do
system("afplay '#{path.expand}'")
end
rescue Timeout::Error
system("killall afplay") # Why doesn't it stop by itself?!?!
rescue Interrupt
puts
end
def report(hours_meditated, total_hours, label = nil)
hours_left = total_hours - hours_meditated
if hours_left.minutes <= 0
puts "<bold>~</bold> #{label ? "#{label}:" : 'Meditated'} <green>#{hours_meditated}</green> hours out of <yellow>#{total_hours}</yellow>."
else
puts "<bold>~</bold> #{label ? "#{label}:" : 'Meditated'} <green>#{hours_meditated}</green> hours out of <yellow>#{total_hours}</yellow> (<green>#{hours_left}</green> left)."
end
rescue => e
require 'pry'; binding.pry ###
end
case ARGV.shift
when 'play'
recording = find_recording(data)
unless recording
abort "<bold>~</bold> Done! You can start using <green>LifeFlow 2.0 Bonus</green> now."
end
start_time = Time.now
play(File.join(base_dir, recording))
duration = Hour.new(0, (Time.now - start_time).round) / 60
if duration.minutes > 5 # Less than 5 minutes doesn't count.
data[recording][start_time] = duration
serialised_data = data.reduce(Hash.new) do |buffer, (key, values)|
buffer.merge(key =>
values.reduce(Hash.new) { |b, (time, duration)|
b.merge(time => duration.to_s)
})
end
data_string = serialised_data.to_yaml
File.open(PATH.expand, 'w') do |file|
file.puts(data_string)
end
puts "<bold>~</bold> Duration: <green>#{duration} minutes</green>."
hours_meditated = data[recording].values.reduce(:+)
report(hours_meditated, TIME_MEDITATED_PER_RECORDING)
end
when 'stats'
require 'date'
recordings.each do |recording|
next if data[recording].empty?
hours_meditated = data[recording].values.reduce(:+)
report(hours_meditated, TIME_MEDITATED_PER_RECORDING, recording)
end
puts
((Date.today - 14)..Date.today).group_by { |date| date.cweek }.each do |_, dates|
dates.each do |date|
hours_per_day = data.values.reduce(Hour.new(0)) do |sum, records|
duration_per_track = records.
# 4 AM till 4 AM of the following day.
select { |time, _| ((date.to_time + 4 * 60 * 60)..((date + 1).to_time + 4 * 60 * 60)).include?(time) }.
reduce(Hour.new(0)) { |result, (_, duration)| result + duration }
sum + duration_per_track
end
hours_per_day_colour = if hours_per_day <= Hour.new(0, 20) then 'bright_black'
elsif hours_per_day > Hour.new(0, 20) && hours_per_day <= Hour.new(1) then 'yellow'
elsif hours_per_day > Hour.new(1) && hours_per_day <= Hour.new(3) then 'blue.bold'
else 'red' end
print "<#{hours_per_day_colour}>#{date.strftime('%a')}</#{hours_per_day_colour}>: #{hours_per_day} "
end
puts
end
else
abort DATA.read
end
__END__
lifeflow play <bright_black># Play the whole current episode.</bright_black>
lifeflow play <yellow>25</yellow> <bright_black># Play the current episode for 25 minutes.</bright_black>
lifeflow stats <bright_black># Stats for the episodes.</bright_black>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment