#! /bin/bash
# Last edited on 2019-10-28 13:06:52 by jstolfi

# Plots files of time intervals for various exchanges.
# The plot (a PNG image) is written to {stdout}.

# Arguments are 
#
#   [ "SHOW" | "NOSHOW" ] {TITLE} {PINIDATE} {PFINDATE} { {INTFILE} {TAG} }...
#
# where {TITLE} is the plot title, 
# {PINIDATE} {PFINDATE} is an interval of dates 
# for the X-axis in the format "{yyyy}-{mm}-{dd}",
# each {INTFILE} is the name of an interval file, and 
# {TAG} is a short title for its plot key.
# 
# The {INTFILE} should contain lines of the form
#
#  {INIDATE} {INITIME} {FINDATE} {FINTIME} {EX} {CR} {TU}
#
# where
#
# {INIDATE} is a starting date, "{yyyy}-{mm}-{dd}".
# {INITIME} is a time in that date, "{HH}:{MM}:{SS}"
# {FINDATE} is an ending date, "{yyyy}-{mm}-{dd}".
# {FINTIME} is a time in that date, "{HH}:{MM}:{SS}"
# {EX} is the exchange code, e.g. "BSTP", "MGOX".
# {CR} is the currency code, e.g. "USD", "CNY".
# {TU} is sampling time interval, e.g. "01h", "01d", etc., or "trans" for transaction logs.

show="$1"; shift
title="$1"; shift
pinidate="$1"; shift
pfindate="$1"; shift
files=()
tags=()
nf=0
while [[ $# -ge 2 ]]; do
  files[${nf}]="$1"; shift;
  tags[${nf}]="$1"; shift;
  nf=$(( ${nf} + 1 ))
done
printf "%d files\n" "${nf}" 1>&2
if [[ $# -gt 0 ]]; then 
  echo "** unpaired arg \"$1\"" 1>&2 ; exit 1
fi

color=( '#0022ff' '#ff0000' '#008800' '#8800dd' '#dd4400' '#0066ff' )

tmp="/tmp/$$"
 
pngfull="${tmp}-full.png"
pngout="${tmp}.png"
rm -f ${pngfull} ${pngout} 

# Create the gnuplots command file:
rm -f ${tmp}.gpl
sep='plot'
kf=0; # File index
kc=0; # Color index
yini=0; # Initial Y-coordinate
yf=${yini}; # Y-coordinate
while [[ ${kf} -lt ${nf} ]]; do
  file="${files[${kf}]}";
  tag="${tags[${kf}]}";
  clr="${color[${kc}]}"
  printf "%s \\\\\n" "${sep}" >> ${tmp}.gpl
  printf "  \"%s\" using (tcol(1)):(column(0)+%d):(vlength(1,3)):(0) \\\\\n" "${file}"  "${yf}">> ${tmp}.gpl
  printf "    title '%s' with vectors nohead lt 1 lw 2.0 lc rgb '#227700', \\\\\n" "${tag}" >> ${tmp}.gpl
  printf "  \"\" using (tcol(3)+dxlabel):(column(0)+%d+dylabel):(flabel(1,3)) \\\\\n" "${yf}" >> ${tmp}.gpl
  printf "    notitle with labels center font 'courbd,14' lc rgb '#ff2200'" >> ${tmp}.gpl
  sep=','
  kf=$(( ${kf} + 1 ))
  # Count the lines:
  ne=`cat ${file} | grep -e '^20' | wc -l`
  printf "${file} = %d intervals\n" "${ne}" 1>&2
  # Shift the next plot:
  yf=$(( ${yf} + ${ne} + 1 ))
  # Get the next color:
  kc=$(( ${kc} + 1 ))
  if [[ ${kc} -ge ${#color[@]} ]]; then kc=0; fi
done
printf "\n" >> ${tmp}.gpl
yfin=${yf}; # Final Y coordinate.

export GDFONTPATH=.

gnuplot <<EOF
set term png size 2400,1200 font "courbd,24"
set output "${pngfull}"
set title "${title}" 

# Time format for {timecolumn}
timeformat = "%Y-%m-%d %H:%M:%S"

xtimefmt = "%Y-%m-%d" # Format for X-axis labels.
pinisecs = strptime(xtimefmt, "${pinidate}")
pfinsecs = strptime(xtimefmt, "${pfindate}")
set xrange [(pinisecs):(pfinsecs)]

hoursecs = 60 * 60       # One hour in seconds.
daysecs = 24 * hoursecs   # One day in seconds.
weeksecs = 7 * daysecs   # One week in seconds.
monthsecs = 4 * weeksecs # One "lunar" month in seconds.

# Decide spacing {mtksecs} between minor tics, and 
# number {nmtk} of minor tics per interval:
rawmtksecs = int((pfinsecs - pinisecs)/70)
if (rawmtksecs <= hoursecs) {
  # Hours and bi-days
  mtksecs = hoursecs; nmtk = 12
} else { if (rawmtksecs <= daysecs) { 
  # Days and weeks
  mtksecs = daysecs; nmtk = 7
} else { if (rawmtksecs <= weeksecs) { 
  # Weeks and quarters
  mtksecs = weeksecs; nmtk = 12
} else { if (rawmtksecs <= 2*weeksecs) { 
  # Biweeks and quarters
  mtksecs = 2*weeksecs; nmtk = 6
} else { if (rawmtksecs <= monthsecs) { 
  # Months and years:
  mtksecs = monthsecs; nmtk = 12
} else { if (rawmtksecs <= 2*monthsecs) { 
  # Bimonths and years:
  mtksecs = 2*monthsecs; nmtk = 6
} else { if (rawmtksecs <= 3*monthsecs) { 
  # Quarters and bi-years:
  mtksecs = 3*monthsecs; nmtk = 8
} else { if (rawmtksecs <= 6*monthsecs) { 
  # Semesters and half-decades:
  mtksecs = 6*monthsecs; nmtk = 10
} else {
  # Years and decades:
  mtksecs = 12*monthsecs; nmtk = 10
}}}}}}}}

# Place down the tics:

k = 0
xtime = (int((pinisecs+mtksecs-1)/mtksecs) - 1)*mtksecs
set xtics ( )
unset mxtics 
# Loop on tics
while (xtime <= pfinsecs) {
    minor = ((k % nmtk) != 0)
    set xtics add ( strftime(xtimefmt, xtime) xtime minor )
    k = k + 1
    xtime = xtime + mtksecs
}
set grid xtics lt 1 lw 3 lc rgb '#ffddaa', lt 1 lw 1.5 lc rgb '#ffddaa'

set yrange [(${yini}-1.5):(${yfin}+1.5)]
set ytics 5
set mytics 5
set grid ytics lt 1 lw 3 lc rgb '#ffddaa', lt 1 lw 1.5 lc rgb '#ffddaa'

set key left

tcol(k) = strptime(timeformat,(strcol(k).' '.strcol(k+1)))
#dxlabel = 5*24*60*60
dxlabel = 0
dylabel = -0.30
vlength(i,k) = tcol(k) - tcol(i)

flabel(r,s) = (stringcolumn(r).'-'.stringcolumn(r+1).'--'.stringcolumn(s).'-'.stringcolumn(s+1))

load "${tmp}.gpl"

EOF

if [[ -s ${pngfull} ]]; then 
  convert ${pngfull} -resize '50%' ${pngout}
  if [[ "/${show}" == "/SHOW" ]]; then
    display ${pngout}
  fi
  cat ${pngout}
fi

rm -f ${tmp}-* ${tmp}.*
