Created
May 29, 2019 14:54
-
-
Save botanicus/d465a81dcb9a57250b9cce5178aac46e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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