

linear_velocity <- function(v, t) {
  diffNA(v) / diffNA(t)
}
linear_acceleration <- function(v, t) {
  diffNA(diffNA(v) / diffNA(t)) / diffNA(t)
}

acceleration_score_actual <- function(v, t, a=0.9) {
  accel <- linear_acceleration(v=v, t=t)
  exponential_avg(accel, a=a)
}
acceleration_score_sign <- function(v, t, a=0.9) {
  accel <- linear_acceleration(v=v, t=t)
  exponential_avg(sign(accel), a=a)
}
velocity_score_actual <- function(v, t, a=0.9) {
  accel <- linear_velocity(v=v, t=t)
  exponential_avg(accel, a=a)
}
velocity_score_sign <- function(v, t, a=0.9) {
  accel <- linear_velocity(v=v, t=t)
  exponential_avg(sign(accel), a=a)
}
createScoreDT <- function(DT, valueCol, timeCol, byCols, fillValue=0) {
  is.char_of_length1(timeCol)
  is.char_of_length1(valueCol)

  key.bak <- key(DT)
  on.exit(setkeyIfNot(DT, key.bak, verbose=FALSE))

  if (timeCol %ni% key(DT))
    warning ("Make sure that the DT is ordered by or keyed by timeCol '", timeCol, "'")

  byCols <- setdiff(byCols, timeCol)

  if (any(wh <- byCols %ni% names(DT)))
    warning(warningCols("Some byCols are not in the DT: ", byCols[wh]))

  if (!length(byCols))
    warning ("There are no byCols")

  ## FILL IN ANY MISSING DATES
  setkeyIfNot(DT, c(timeCol, byCols), verbose=TRUE, organize=TRUE)
  DT[, ..na_value := is.na(get(valueCol))]
  cjd <- CJ_allDatesByCols(DT, dateCol=timeCol, byCols=byCols)
browser(text="")
  DTnew <- DT[cjd][ is.na(..na_value), (valueCol) := fillValue]
  DT[, c("..na_value") := NULL]
  setkeyIfNot(DT, key.bak)
  
  DTnew[, 
    list (
      acceleration_score_actual = acceleration_score_actual (get(valueCol), get(timeCol))
      ,acceleration_score_sign  = acceleration_score_sign   (get(valueCol), get(timeCol))
      ,velocity_score_actual    = velocity_score_actual     (get(valueCol), get(timeCol))
      ,velocity_score_sign      = velocity_score_sign       (get(valueCol), get(timeCol))
    ), keyby = byCols]
}



## ~~~~~~~~~~ FOR REFERENCE ~~~~~~~~~~~~~~~~
if (FALSE) {
  DTnew <- DT[cjd][ is.na(..na_value), (valueCol) := fillValue]
  CJ.expand_DT_by_columns <- function(DT, byCols, allow.cartesian=FALSE) {
    K <- lapply(DT[, byCols, with=FALSE], unique) %>% do.call(CJ, .)

    setkeyIfNot(copy(DT), byCols, verbose=FALSE)[K, allow.cartesian=allow.cartesian]
  }
}
