You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

325 lines
8.9 KiB
Bash

#!/usr/bin/env bash
# this script enables water tracking in tmux status bar via a simple command
usage() {
cat <<EOF
usage: $0 [-chr][-s|S][-u|U QTY] [WATER]
Options:
-c, --colorize enables tmux color options
-s, --symbol enables static nerdfont compaitable symbol
-S enables dynamic nf symbol
-u, --undo removes the last entry
-U removes the last QTY entries.
use all as QTY to remove all entries
-r, --reminder creates a tmux pop up to remind you to hydrate
-h, --help display this message
The reminder works based on specified water goals
Defaults to 32 ounces by 10 am, 64 by 1 pm, 96 by 5 pm, and 128 by 8 pm
Goals are defined in the script itself.
If a sub goal is not reached, the reminder will trigger
Reminders have a dismiss option as well as an entry box to enter the water drank
Reminders will pop up every 30 minutes until the goal is reached
The WATER arguement is an integer and will be added to the current total.
If a mistake is made, -u can remove the faulty entry.
EOF
exit $1
}
DATE=$(date +%b_%d_%y)
TIME=$(date +%H:%M:%S)
WATER_DIR="$HOME/.dotfiles/bin/water"
WATERFILE="${WATER_DIR}/${DATE}.csv" # makes it easy to reset on each new day
# customize goal amt and timings.
# checks based on current input and then cross references with goals
# linear calc so in this example 32 by 10, 64 by 13 etc.
####################################
GOAL_AMT=128 # fl. oz.
GOALS=( "10:00" "13:00" "16:00" "20:00" )
SNOOZE=30 # time between reminders (minutes)
####################################
# Colors
RED='#[fg=color1]'
YELLOW='#[fg=color3]'
LIGHT_YELLOW='#[fg=color226]'
LIGHT_GREEN='#[fg=color112]'
GREEN='#[fg=color21]'
BLUE='#[fg=color33]'
# Symbols to use
STATIC_SYMBOL='\uf6aa'
# from empty -> full
DYNAMIC_SYMBOL=( '\uf58d' '\uf579' '\uf57a' '\uf57b' '\uf57c' '\uf57d' '\uf57e' '\uf57f' '\uf580' '\uf581' '\uf578' )
get_current_amt() {
# gets the current water intake
if [[ ! -f "$WATERFILE" ]] ; then
# no waterfile
# archiving old file
mv ${WATER_DIR}/*.csv ${WATER_DIR}/archive
# creating new file for the day
printf 'Time, Change, Running Total\n' > "$WATERFILE"
printf '%s, 0, 0\n' "$TIME" >> "$WATERFILE"
else
# waterfile exists
CURRENT_WATER=$(cat $WATERFILE | tail -n 1 | awk '{print $3}')
fi
}
reminder() {
# checks and creates a reminder
if [[ -z "$TMUX" ]] ; then
echo "TMUX required for reminder!"
exit 1
fi
# this will round up
goal_incr=$((($GOAL_AMT + ${#GOALS[@]}-1) / ${#GOALS[@]}))
# index of the time to check in $GOALS
cur_indx=$(($CURRENT_WATER / $goal_incr))
if [[ $CURRENT_WATER -lt $GOAL_AMT ]] ; then
# goals not finished, check pace
time_unix=$(date -d "$TIME" +%s)
# expired is goaltime - current time
expired=$(( $(date -d "${GOALS[$cur_indx]}" +%s) - $time_unix))
if [[ $expired -lt 0 ]] ; then
# goal missed, check snooze
source "$WATER_DIR/.reminder" 2>/dev/null
# check elapsed
if [[ $time_unix -gt $REMINDER_SNOOZE ]] ; then
# trigger reminder
goal=$(( ($GOAL_AMT * ($cur_indx + 1)) / ${#GOALS[@]}))
fmt_time=$(date -d "${GOALS[$cur_indx]}" "+%l:%M %P")
rem_info=$(printf 'You have only drank %d fl. oz. while your goal is to drink %d fl. oz. by %s!\n\nThis reminder will reappear in %d minutes unless you consume fluids!\n\nOptionally, mute this reminder until tomorrow' $CURRENT_WATER $goal "$fmt_time" $SNOOZE)
tmux display-popup -E\
dialog\
--title 'DEHYDRATION ALERT'\
--yes-label 'Dismiss'\
--no-label 'Mute'\
--yesno \
"$rem_info" 0 0
# check for mute
if [[ $? == 1 ]] ; then
# muted until tomorrow
TTS=$(date -d "tomorrow 00:00:00" +%s)
else
TTS=$(date -d "+ $SNOOZE minutes" +%s)
fi
# update last_reminder
printf 'REMINDER_SNOOZE=%d\n' $TTS > "$WATER_DIR/.reminder"
fi
fi
fi
}
update_water() {
# updates water based on $WATER_CHANGE
CURRENT_WATER=$(($CURRENT_WATER + $WATER_CHANGE))
# putting in file
printf '%s, %d, %d\n' "$TIME" $WATER_CHANGE $CURRENT_WATER >> "$WATERFILE"
}
undo_changes() {
# removes specifed entries
# gets the lines of entries
WATER_LINES=$(($(wc -l < "$WATERFILE") - 2))
if [[ $WATER_LINES -gt 0 ]] ; then
# removing entries
if [[ "$1" == "all" || "$1" == "ALL" ]] ; then
# force a reset
REMOVAL=$WATER_LINES
elif [[ $1 =~ ^[0-9]+$ ]] ; then
# remove $1 changes
if [[ $1 -gt $WATER_LINES ]] ; then
printf 'Only %d entries\n' $WATER_LINES
REMOVAL=$WATER_LINES
else
REMOVAL=$1
fi
else
printf 'Arguement %s not recognized\n' "$1"
usage
exit 1
fi
choice=$(bash -c "read -p 'Are you sure you want to remove $REMOVAL entries? (y/n)' -n 1 -r c; echo \$c")
echo ""
if [[ $choice =~ ^[Yy]$ ]] ; then
# remove
if [[ $WATER_LINES -gt $REMOVAL ]] ; then
# removing specified lines
last_line=$(($WATER_LINES - $REMOVAL + 3)) # account for offset
sed -i "$last_line ,$ d" "$WATERFILE"
else
# essentially a reset
printf 'Time, Change, Running Total\n' > "$WATERFILE"
printf '%s, 0, 0\n' "$TIME" >> "$WATERFILE"
fi
# updating amount
get_current_amt
fi
echo "Removed $REMOVAL entries!"
else
echo "Nothing to remove!"
fi
}
colorize() {
# sends water intake level through conditionals to be colorized
if [[ $1 -lt 32 ]] ; then
color="$RED"
elif [[ $1 -lt 64 ]] ; then
color="$YELLOW"
elif [[ $1 -lt 96 ]] ; then
color="$LIGHT_YELLOW"
elif [[ $1 -lt 128 ]] ; then
color="$LIGHT_GREEN"
else
color="$GREEN"
fi
# avoids newlines
printf '%s' "$color"
}
print_water() {
# formats and prints $CURRENT_WATER
if [ "$SYMBOL" == "dynamic" ] ; then
# getting dynamic symbol
# rounding down
symb_indx=$(echo "scale=1; indx=($CURRENT_WATER / $GOAL_AMT) * ${#DYNAMIC_SYMBOL[@]}; scale=0; indx/1" | bc)
if [[ $symb_indx -ge ${#DYNAMIC_SYMBOL[@]} ]] ; then
# trimming
symb_indx=$((${#DYNAMIC_SYMBOL[@]}-1))
fi
# if colors are enabled, colorize the symbol
if [ "$COLORIZE" = true ] ; then
clr="$BLUE"
fi
printf '%s%s ' "$clr" $(echo -e "${DYNAMIC_SYMBOL[$symb_indx]}")
elif [[ "$SYMBOL" == "static" ]] ; then
# space for double wide
printf '%s ' "$STATIC_SYMBOL"
fi
if [ "$COLORIZE" = true ] ; then
dflt="#[default]"
printf '%s' "$(colorize $CURRENT_WATER)"
fi
printf '%d%s\n' $CURRENT_WATER "$dflt"
# checks for a reminder
if [[ "$REMINDER" = true ]] ; then
# reminders enabled
reminder
fi
}
# make dir on fresh installs
if [[ ! -d "${WATER_DIR}/archive" ]] ; then
mkdir -p "${WATER_DIR}/archive"
fi
# get the current amount
get_current_amt
# transform long form args
for arg in "$@"; do
shift
case "$arg" in
'--help') set -- "$@" "-h" ;;
'--colorize') set -- "$@" "-c" ;;
'--reminder') set -- "$@" "-r" ;;
'--undo') set -- "$@" "-u" ;;
'--symbol') set -- "$@" "-s" ;;
*) set -- "$@" "$arg" ;;
esac
done
# parsing args
while getopts "hcrsSuU:" opt ; do
case "$opt" in
'c' )
COLORIZE=true
;;
's' )
[ -n "$SYMBOL" ] && usage 1 || SYMBOL="static"
;;
'S' )
[ -n "$SYMBOL" ] && usage 1 || SYMBOL="dynamic"
;;
'u' )
[ -n "$UNDO" ] && usage 1 || UNDO=1
;;
'U' )
[ -n "$UNDO" ] && usage 1 || UNDO="$OPTARG"
;;
'r' )
REMINDER=true
;;
'h' )
usage
;;
'?' )
usage 1 >&2
;;
esac
done
# check for undo first
if [[ ! -z "$UNDO" ]] ; then
undo_changes "$UNDO"
fi
# get the change (if any)
shift $(($OPTIND - 1))
WATER_CHANGE=$1
# update totals
if [[ ! -z "$WATER_CHANGE" ]] ; then
# prevent empty/0 updates
update_water
fi
# return the new total
# Could make this an opt, but it seems to be a good default behavior
print_water