'Forecast.R'
     'Data.R'
     'A_NAMESPACE.R'
+    'J_LastValue.R'
 
                        if (!opera)
                                tdays = setdiff(tdays, today) #always exclude current day
 
-                       # Shortcut if window is known #TODO: cross-validation for number of days, on similar (yerste)days
+                       # Shortcut if window is known
                        if (hasArg("window"))
                        {
                                return ( private$.predictShapeAux(data, tdays, today, predict_from, horizon,
                                best_window_exo = optimize(
                                        errorOnLastNdays, c(0,7), simtype="exo")$minimum
                        }
+                       if (local)
+                       {
+                               best_window_local = optimize(
+                                       errorOnLastNdays, c(3,30), simtype="none")$minimum
+                       }
 
                        best_window =
                                if (simtype == "endo")
                                        best_window_exo
                                else if (simtype == "mix")
                                        c(best_window_endo,best_window_exo)
-                               else #none: value doesn't matter
-                                       1
+                               else #none: no value
+                                       NULL
+                       if (local)
+                               best_window = c(best_window, best_window_local)
 
                        return( private$.predictShapeAux(data, tdays, today, predict_from, horizon, local,
                                best_window, simtype, opera, TRUE) )
                        if (local)
                        {
                                # limit=Inf to not censor any day (TODO: finite limit? 60?)
-                               tdays = getSimilarDaysIndices(today, data, limit=Inf, same_season=TRUE,
+                               tdays <- getSimilarDaysIndices(today, data, limit=Inf, same_season=TRUE,
                                        days_in=tdays_cut, operational=opera)
+                               nb_neighbs <- round( window[length(window)] )
                                # TODO: 10 == magic number
-                               tdays = .getConstrainedNeighbs(today, data, tdays, min_neighbs=10)
+                               tdays <- .getConstrainedNeighbs(today, data, tdays, min_neighbs=nb_neighbs)
                                if (length(tdays) == 1)
                                {
                                        if (final_call)
                                        {
                                                private$.params$weights <- 1
                                                private$.params$indices <- tdays
-                                               private$.params$window <- 1
+                                               private$.params$window <- window
                                        }
                                        return ( data$getSerie(tdays[1])[predict_from:horizon] )
                                }
-                               max_neighbs = 12 #TODO: 10 or 12 or... ?
+                               max_neighbs = nb_neighbs #TODO: something else?
                                if (length(tdays) > max_neighbs)
                                {
                                        distances2 <- .computeDistsEndo(data, today, tdays, predict_from)
 
                        if (simtype == "endo" || simtype == "mix")
                        {
-                               # Compute endogen similarities using given window
-                               window_endo = ifelse(simtype=="mix", window[1], window)
-
                                # Distances from last observed day to selected days in the past
                                # TODO: redundant computation if local==TRUE
                                distances2 <- .computeDistsEndo(data, today, tdays, predict_from)
 
-                               simils_endo <- .computeSimils(distances2, window_endo)
+                               # Compute endogen similarities using the given window
+                               simils_endo <- .computeSimils(distances2, window[1])
                        }
 
                        if (simtype == "exo" || simtype == "mix")
                        {
-                               # Compute exogen similarities using given window
-                               window_exo = ifelse(simtype=="mix", window[2], window)
-
                                distances2 <- .computeDistsExo(data, today, tdays)
 
+                               # Compute exogen similarities using the given window
+                               window_exo = ifelse(simtype=="mix", window[2], window[1])
                                simils_exo <- .computeSimils(distances2, window_exo)
                        }
 
                        {
                                private$.params$weights <- similarities
                                private$.params$indices <- tdays
-                               private$.params$window <-
-                                       if (simtype=="endo")
-                                               window_endo
-                                       else if (simtype=="exo")
-                                               window_exo
-                                       else if (simtype=="mix")
-                                               c(window_endo,window_exo)
-                                       else #none
-                                               1
+                               private$.params$window <- window
                        }
 
                        return (prediction)
 
 #'
 #' @section Methods:
 #' \describe{
-#' \item{\code{initialize(data, pjump)}}{
-#'   Initialize a Forecaster object with a Data object and a jump prediction function,
-#'   or NULL if \code{predictShape()} returns an adjusted curve.}
+#' \item{\code{initialize(pjump)}}{
+#'   Initialize a Forecaster object with a jump prediction function.}
 #' \item{\code{predictSerie(data,today,memory,predict_from,horizon,...)}}{
 #'   Predict the next curve (at index today) from predict_from to horizon (hours), using
 #'   \code{memory} days in the past.}
                        if (is.na(predicted_shape))
                                return (NA)
 
-                       predicted_delta <-
-                               if (is.null(private$.pjump))
-                                       NULL
-                               else
-                                       private$.pjump(data,today,memory,predict_from,horizon,private$.params,...)
+                       predicted_delta <- private$.pjump(data, today, memory, predict_from,
+                                       horizon, private$.params, first_pred=predicted_shape[1], ...)
 
-                       # Predicted shape is aligned on the end of current day + jump (if jump!=NULL)
+                       # Predicted shape is aligned on the end of current day + jump
                        c( data$getSerie(today)[if (predict_from>=2) 1:(predict_from-1) else c()],
-                               predicted_shape + ifelse( is.null(private$.pjump),
-                                       0,
-                                       predicted_delta - predicted_shape[1] +
-                                               ifelse(predict_from>=2,
-                                                       data$getSerie(today)[predict_from-1], tail(data$getSerie(today-1),1)) ) )
+                               (predicted_shape - predicted_shape[1]) + #shape with first_pred = 0
+                               ifelse(predict_from>=2, #last observed value
+                                       data$getSerie(today)[predict_from-1], tail(data$getSerie(today-1),1)) +
+                               predicted_delta ) #jump
                },
                predictShape = function(data, today, memory, predict_from, horizon, ...)
                        NULL #empty default implementation: to implement in inherited classes
 
--- /dev/null
+#' getLastValueJumpPredict
+#'
+#' Just predict zero "jump" (for reference, benchmarking at least).
+#'
+#' @inheritParams computeForecast
+#' @inheritParams getZeroJumpPredict
+#'
+#' @aliases J_LastValue
+#'
+getLastValueJumpPredict = function(data, today, memory, horizon, params, ...)
+{
+       0
+}
 
 #' getZeroJumpPredict
 #'
-#' Just predict zero "jump" (for reference, benchmarking at least).
+#' "Reset level to 0": jump by -A where A is the last observed value.
 #'
 #' @inheritParams computeForecast
 #' @param today Index of the current day (predict tomorrow)
 #'
 getZeroJumpPredict = function(data, today, memory, horizon, params, ...)
 {
-       0
+       list(...)$first_pred - ifelse( predict_from >= 2,
+               data$getSerie(today)[predict_from-1], tail(data$getSerie(today-1),1) )
 }
 
 #'   \itemize{
 #'     \item Persistence : use last (similar) day
 #'     \item Neighbors: re-use the weights from F_Neighbors
-#'     \item Zero: just output 0 (no adjustment)
+#'     \item LastValue: start serie with last observed value
+#'     \item Zero: no adjustment => use shape prediction only
 #'   }
-#'   If pjump=NULL, then no adjustment is performed (output of \code{predictShape()} is
-#'   used directly).
 #' @param predict_from First time step to predict.
 #' @param memory Data depth (in days) to be used for prediction.
 #' @param horizon Last time step to predict.
 #' ts_data <- system.file("extdata","pm10_mesures_H_loc.csv",package="talweg")
 #' exo_data <- system.file("extdata","meteo_extra_noNAs.csv",package="talweg")
 #' data <- getData(ts_data, exo_data, limit=200)
-#' pred <- computeForecast(data, 100:130, "Persistence", "Zero",
+#' pred <- computeForecast(data, 100:130, "Persistence", "LastValue",
 #'   predict_from=8, memory=50, horizon=12, ncores=1)
 #' \dontrun{
 #' #Sketch for real-time mode:
                stop("Indices out of range")
        if (!is.character(forecaster))
                stop("forecaster (name): character")
-       if (!is.null(pjump) && !is.character(pjump))
-               stop("pjump (function): character or NULL")
+       if (!is.character(pjump))
+               stop("pjump (function): character")
 
        pred = Forecast$new( sapply(indices, function(i) integerIndexToDate(i,data)) )
        forecaster_class_name = getFromNamespace(
                paste(forecaster,"Forecaster",sep=""), "talweg")
 
-       if (!is.null(pjump))
-               pjump <- getFromNamespace(paste("get",pjump,"JumpPredict",sep=""), "talweg")
+       pjump <- getFromNamespace(paste("get",pjump,"JumpPredict",sep=""), "talweg")
        forecaster = forecaster_class_name$new(pjump)
 
        computeOneForecast <- function(i)
 
 -----r
 p1 = computeForecast(data, indices, "Neighbors", "Neighbors",
        predict_from=P, horizon=H, simtype="mix", local=FALSE)
-p2 = computeForecast(data, indices, "Neighbors", NULL,
+p2 = computeForecast(data, indices, "Neighbors", "Zero",
        predict_from=P, horizon=H, simtype="none", local=TRUE)
-p3 = computeForecast(data, indices, "Average", "Zero",
+p3 = computeForecast(data, indices, "Average", "LastValue",
        predict_from=P, horizon=H)
-p4 = computeForecast(data, indices, "Persistence", "Zero",
+p4 = computeForecast(data, indices, "Persistence", "LastValue",
        predict_from=P, horizon=H, same_day=TRUE)
 -----r
 e1 = computeError(data, p1, P, H)