R/tg.R

SMART_LABELS =  list(

    MAT="Moving Annual Average",
    MTH="Monthly",
    QTR="Quarterly",
    YR = "Yearly",
    YTD = "Year-to-date",
    MAYTD = 'YTD: Moving Annual Average',
    MM1 = '1-month % change',
    MM3 = '3-month % change',
    MM12 = '12-month % change',
    QQ1 = '1-quarter % change',
    HY1 = 'Half-yearly % change',
    QQ4 = '4-quarter % change',
    YY1 = '1-year % change',
    MAT1 = 'MAT: 1-month % change',
    MQT1 = 'MAT: 1-quarter % change',
    MAT12 = 'MAT: 12-month % change',
    MAT4 = 'MAT: 4-quarter % change',
    YTD1 = 'YTD: 1-month % change',
    YQT1 = 'YTD: 1-quarter % change',
    YTD4 = 'YTD: 4-quarter % change',
    YTD12 = 'YTD: 12-month % change',
    MAYTDM1 = 'YTD-MA: 1-month % change',
    MAYTDM12 ='YTD-MA: 12-month % change',
    MAYTDQ1 = 'YTD-MA: 1-quarter % change',
    MAYTDQ4 = 'YTD-MA: 4-quarter % change'
)

BREXIT_POINT = "2016-06-23"


#'Helper class for aggregation and generating growth from timeseries object
#'

tg <- R6::R6Class(
    "tg",
    inherit = tp_utils,

    public = list(

        data_df = NULL,  # input dataframe
        data_raw = NULL, # unformatted data input
        data_ts = NULL,  # input timeseries
        data_freq = NULL, # frequency of timeseries data
        data_count = NULL, # number of data points
        data_format = 4,   # data format 0=from db, 1 = timeseries object, 2 = dataframe, 3 = vector
        data_start = NULL, # starting point of timeseries data
        data_agg = NULL,   # holds aggregated format (eg monthly to quarterly, quarterly to yearly)
        data_agg_to = NULL, # destination format
        data_fx = 1,        # data periodicity
        data_growth = NULL, # growth timeseries object
        data_growth_fx = NULL, # growth periodicity
        data_code = NULL,
        data_days = NULL,
        db_agg = 'sum',


        db_sql = NULL, #query to fetch data from database
        db_df = NULL,  #query results in dataframe format
        db_ts = NULL,  #query resutls in timeseries format
        db_freq = NULL, #timeseries frequency
        db_limit = list(yr = NULL, mth = NULL),


        #data format values
        DB = 0, TS = 1,DF=2,VEC = 3, UNKNOWN = 4,

        #data periods
        MTH=0, QTR = 1, YR = 2, YTD=3, MAT= 4, MQT=5, NOTKNOWN = 6, MAYTD = 7, HY = 8,



        initialize = function(x, x_start=NULL, x_frq = NULL, db_limit = list(yr=NULL, mth=12), db_name = NULL, db_agg = 'sum' ){

            super$initialize( db_name )

            self$set_brexit_text()

            self$data_raw <- x
            if( ! is.null( db_limit$yr )){ self$data_days <- with(db_limit, 372 * yr + 31 * mth + 1 ) }

            self$set_data_format(self$data_raw)

            if(self$data_format == self$UNKNOWN ){
                cat("Unknown data format. Format should be : Timeseries, Dataframe or Vector\n")
                return(NULL)
            }

            if(self$data_format == self$DB){

                if(!is.null(x_start)){ self$set_data_start(x_start) }
                if(!is.null(x_frq)){ self$set_data_frequency(x_frq) }
                self$set_db_ts_properties()

            }else{

                self$set_data_start(x_start)
                self$set_data_frequency(x_frq)
                self$set_data_ts()
                self$set_data_df()
            }
        },

        #'set growth periodicity
        #'monthly, quarter, etc
        set_growth_fx =function(value){
            if(!is.null(value) && value %in% private$MM1:private$NOTHING){
                self$data_growth_fx <- value
            }else{
                cat("Invalid growth rate \n")
            }
            invisible(self)
        },

        set_db_agg = function( value){

            if(!is.null(value) ){
                self$db_agg <- value
            }
            invisible(self)

        },

        set_db_limit = function(value){

            if(!is.null(value) ){
                self$db_limit <- value
            }
            invisible(self)

        },

        #'get growth periodicity
        get_growth_fx = function(){
            return(self$data_growth_fx)
        },

        #'get growth data
        #'fx = growth function to use
        #'  mm1 = "current month compared to pervious month"
        #'  mm3 = "current month compared to 3 months ago"
        #'  mm12 = "current month compared to a year ago"
        #'  qq1 = "current quarter compared with pervious quarter"
        #'  qq4 = "current quarter compared to a year ago
        #'  yy1 = "current year compared to previous year"
        #'  mat1 = "moving annual total compared to a year ago"
        #'  mqt1 = "moving quarterly total compared to a quarter ago"
        #'  mqt4 = "moving quarterly total compared to a year ago"
        #'  ytd12 = "monthly year to date compared to previous year"
        #'  ydt4 = "quarterly year to date compared to previous year"
        #'
        #'ops = operation to perform, either "sum" or "avg"

        get_growth_data = function(fx='mm12', ops='sum'){

            self$data_growth<- switch( fx,
                                       mm1 = self$get_mm1(),
                                       mm3 = self$get_mm2(),
                                       mm12 =self$get_mm12(),

                                       qq1 = self$get_qq1(),
                                       qq4 = self$get_qq4( ops = ops ),

                                       yy1 = self$get_yy1( ops = ops ),

                                       mat1 = self$get_mat1( ops = ops ),
                                       mat4 = self$get_mat4( ops = ops ),
                                       mat12 = self$get_mat12( ops = ops ),

                                       mqt1 = self$get_mqt1( ops = ops ),
                                       mqt4 = self$get_mqt4( ops = ops ),

                                       ytd1 = self$get_ytd1( ops = ops ),
                                       ytd4 = self$get_ytd4( ops = ops ),
                                       ytd12 = self$get_ytd12( ops = ops ),

                                       maytdm1 = self$get_maytdm1( ops = ops ),

                                       NULL

            )
            return( self$data_growth )

        },

        generate_data_code = function(){
            return(
                paste0(
                    'btrends-',
                    lubridate::year(   Sys.Date() ), '-',
                    lubridate::month(  Sys.Date() ), '-',
                    lubridate::day(    Sys.Date() ), '-',
                    lubridate::hour(   Sys.Date() ),
                    lubridate::minute( Sys.Date() ),
                    lubridate::seconds(Sys.Date() )
                )
            )

        },
        #' set format of original data
        set_data_format = function(value){

            if(!missing(value) && !is.null(value)){

                my_format <- self$UNKNOWN

                if( is.data.frame(value) ){

                    my_format <- self$DF

                }else if(is.ts(value)){

                    my_format <- self$TS

                }else if( is.character(value) ){

                    self$data_code <- toupper( value )
                    my_format <- self$DB

                }else if( is.vector(value)){
                    my_format <- self$VEC

                }

                if( !(is.character(value) )){

                    if(!(my_format == self$UNKNOWN)){

                        self$data_code <- self$generate_data_code()

                    }
                }

                self$data_format <- my_format
            }
            invisible(self)
        },

        #' get format of original data
        get_data_format = function(){
            return(
                self$data_format
            )
        },

        #' set start parameter for timeseries object in format
        #' value = c(year,month)
        set_data_start = function(value){

            my_start <-  value

            if( is.null( value )){
                if(self$data_format == self$TS){

                    self$data_start <- stats::start( self$data_raw)

                }else if(self$data_format == self$VEC && !is.null(value)){
                    my_local_start <- value
                    if(length(my_local_start) == 2 ){
                        if( (my_local_start[1] > 1900) && (my_local_start[2] %in% 1:12)){
                            self$data_start <- value
                        }else{
                            cat("Start year or month is out of range\n")
                            return(NULL)
                        }
                    }else {
                        cat("Start should be vector in format (year,month)\n")
                        return(NULL)
                    }

                }else{

                    my_col_names <- tolower(names(self$data_raw))
                    my_col_len <- length(my_col_names)
                    if(my_col_len < 2){
                        cat("Insufficient number of columns. Dataframe should either be in format [yr,mth,value] or [yr,value]\n")
                        return(NULL)
                    }

                    if(my_col_len == 3){
                        if( ("yr" %in% my_col_names) && ("mth" %in% my_col_names)){
                            my_df <- dplyr::arrange(self$data_raw,yr,mth)
                            self$data_start <- c(my_df$yr[1],my_df$mth[1])

                        }else{
                            cat("What meanest thou, o sleeper!\n")
                            cat("Invalid column names: column names should be (yr,mth,value)\n")
                            cat("Perhaps you need a coffee break\n")
                            return(NULL)
                        }
                    }else{
                        if( ("yr" %in% my_col_names) ){
                            my_df <- dplyr::arrange(self$data_raw,yr)
                            self$data_start <- c(my_df$yr[1])
                        }else{
                            cat("Invalid column names: column names should be (yr,value) or (yr,mth,value)\n")
                            return(NULL)
                        }#if yr

                    }#else 2 columns
                }#DF
            }else{
                self$data_start <- value
            }
            invisible(self)

        },#function set_data_start

        #' get start parameter of orginal timeseries object
        get_data_start = function(){
            return(
                self$data_start
            )
        },

        set_data_frequency = function(value){

            if(is.null( value )){

                if(self$data_format == self$TS){

                    self$data_freq <- stats::frequency( self$data_raw )

                }else if( (self$data_format %in% c(self$VEC,self$DF) ) && !is.null(value) && value %in% 1:365){

                    self$data_freq <- value

                }else if(self$data_format==self$DF && is.null(value)) {

                    if( dim(self$data_raw)[2] == 2){

                        self$data_freq <- 1

                    }else{

                        my_df <- self$data_raw
                        my_yr <- dplyr::distinct(self$data_raw,yr)
                        my_yr <- dplyr::arrange(my_yr,yr)
                        my_yr_n <- nrow(my_yr)

                        if(my_yr_n >2){

                            self$data_freq <- sqldf::sqldf( paste0("select count(yr) as n from my_df where yr =", my_yr$yr[2]) )$n

                        }else{

                            cat("Not enough data to calculate frequency automatically. Please manually supply frequency\n")
                            return(NULL)

                        }
                    } #DF with 3 cols
                } # DF auto freq
            }else{
                self$data_freq <- value
            }
            invisible(self)
        },#function set_freq

        get_data_freq = function(){
            return(
                self$data_freq
            )
        },

        set_data_ts = function(){

            if(self$data_format == self$TS){

                self$data_ts <- self$data_raw

            }else if(self$data_format == self$VEC){

                self$data_ts <- stats::ts( self$data_raw, start=self$data_start, frequency = self$data_freq)

            }else if( self$data_format == self$DF){

                self$data_ts <- stats::ts( self$data_raw$value, start=self$data_start, frequency = self$data_freq)

            }else if(self$data_format == self$DB){

                if(!is.null( self$db_ts )){
                    self$data_ts <- self$db_ts
                }else{
                    self$set_db_ts_properties()
                }
            }

            invisible(self)
        },

        get_data_ts = function(){

            return(
                self$data_ts
            )
        },

        get_data_db = function(){

            my_data <-  self$db_run_sql()
            my_rows <- nrow(my_data)

            if(my_rows > 0){

                self$data_df <- my_rows

                my_yrs <- sqldf::sqldf("select distinct yr from my_data order by yr")

                if(nrow(my_yrs) > 2){
                    my_yr <- my_yrs$yr[2]
                    my_mths <- dplyr::filter(my_data,yr == my_yr)
                    self$data_freq <- nrow(my_mths)
                }else if( nrow(my_yrs) >0){
                    self$data_freq <- 1
                }else{
                    cat("No data for this code = ", self$data_raw,'. Aborting ....\n')
                    return(NULL)
                }
                self$data_ts <- ts( c(my_rows$value), start = self$data_start, frequency = self$data_freq)


            }# rows > 0

        },

        db_get_sql = function(is_force=FALSE){

            if( is.null( self$db_sql )|| is_force){

                where2 <- ""

                if( ! is.null( self$data_days ) ){

                    where2 <- sprintf(" and data_days <= %s ", self$data_days )
                }

                is_multi_code <- length( ( grep(",", self$data_code) == 1 ) ) >0


                sql1 <- sql2 <- NULL

                if(!is_multi_code){
                    sql1 <- "select yr,mth,data_code,data_value as value from trends_data where "
                    sql2 <-  sprintf(" upper( data_code) in ('%s') %s order by yr, mth", toupper( self$data_raw ), where2)

                }else{

                    sql1 <-  sprintf("select a.yr, a.mth,'%s' as data_code , %s(a.data_value) as value from trends_data a where ", self$generate_data_code(), self$db_agg )
                    sql2 <-  sprintf(" upper( a.data_code) in %s %s group by a.yr, a.mth order by a.yr, a.mth", toupper( beamaUtils::split_str( self$data_raw )) , where2)
                }

                self$db_sql <-  paste0( sql1, sql2 )
            }
            return( self$db_sql)
        },

        get_db_sql = function(is_force = FALSE){

            self$db_get_sql(is_force = is_force)

        },

        db_run_sql = function(){

            #cat('SQL = ',self$db_get_sql(),'\n')
            #cat('DB = ', private$global_DB, '\n' )

            my_data <- self$run_sql( self$db_get_sql() )

            #cat('NROW = ', nrow( my_data ), '\n' )

            return(
                my_data

            )

            #return( self$run_sql( self$db_get_sql() ) )

        },

        db_get_data = function(force=FALSE){

            if(!is.null( self$db_ts) && !force) {

                return(self$db_ts)

            }else{

                set_db_ts_properties()

            }
            return( self$db_ts)
        },

        set_db_ts_properties = function(){

            self$db_df <- my_data <- self$db_run_sql()
            #my_data$data_days <- (my_data$yr * 12 + my_data$mth) * 31 + my_data$dy
            #my_data <- dplyr::arrange( my_data, data_days)
            #cat('DB = ', self$db_name,'\n')
            #cat('SQL = ', self$db_sql,'\n')

            if( nrow( my_data ) == 0) {
                cat('Are you sure of the code you have just given me? \n Or is it a time for a tea break? \n Code not in database. Aborting data aquisition ....\n')
                return( NULL )
            }



            if( is.null( self$data_start) ){

                self$data_start <- c( my_data$yr[ 1 ], my_data$mth[ 1 ] )

            }

            #cat('ts_start yr= ', my_data$yr[ 1 ],' ts_start mth=', my_data$mth[ 1 ],' my_data qtr = ', my_data$qtr[ 1],' ts_freq = ', self$data_freq,'\n')

            if( is.null( self$data_freq)){

                my_yrs <- sqldf::sqldf( "select distinct yr from my_data order by yr" )

                if( nrow(my_yrs) > 2){

                    my_yr <- my_yrs$yr[2]
                    my_mths <- dplyr::filter(my_data,yr == my_yr)
                    self$data_freq <- my_frq <- nrow(my_mths)

                    if(self$data_freq == 4){

                        self$data_start <- c( my_data$yr[ 1 ], my_data$mth[ 1 ]/3 )

                    }

                    #cat('ts_start yr= ', self$data_start[ 1 ],' ts_start mth=', self$data_start[ 2 ],'my_data qtr = ',my_data$qtr[1 ],' ts_freq = ', self$data_freq,'\n')


                }else if( nrow(my_yrs) >0){

                    self$data_freq <- 1

                }else {

                    cat("No data for code =",self$data_raw,"\n")
                    return(NULL)

                }
            }

            # my_frq <- NULL
            # my_frq_data <- self$run_sql(
            #     sprintf("select data_frq from trends_meta where upper(data_code) in ('%s') limit 1", toupper( self$data_raw) )
            # )
            #
            #
            # if( nrow( my_frq_data) > 0 ){
            #
            #     my_frq <- self$data_freq <- my_frq_data$data_frq
            #
            # }
            #
            # cat(sprintf("my_frq = %s, my_start(yr,mth,qtr) = c(%s, %s, %s)\n",my_frq,my_data$yr[ 1 ],my_data$mth[ 1 ],my_data$qtr[ 1 ] ))
            #
            # if( is.null( self$data_start) ){
            #
            #     if( my_frq == 12 ){
            #
            #         self$data_start <- c( my_data$yr[ 1 ], my_data$mth[ 1 ] )
            #
            #     }else if (my_frq == 4){
            #
            #         self$data_start <- c( my_data$yr[ 1 ], my_data$qtr[ 1 ] )
            #
            #     }else if (my_frq == 1){
            #
            #         self$data_start <- c( my_data$yr[ 1 ], 1 )
            #
            #     }else {
            #
            #         cat("No data for code =",self$data_raw,"\n")
            #         return(NULL)
            #
            #     }
            # }
            #

            self$db_ts <- ts(c(my_data$value), start = self$data_start, frequency = self$data_freq)
            self$data_ts <- self$db_ts
            self$set_data_df()

            invisible(self)

        },

        db_get_freq = function(){

            if(!is.null( self$db_freq)){

                return( self$db_freq)

            }else if(!is.null( self$db_ts)){

                self$db_freq <- frequency( self$db_ts)
                return( self$db_freq)

            }else if( !is.null(self$db_df )){

                self$set_db_ts_properties ()
                return(self$data_freq)

            }
        },

        get_db_freq = function(){
            self$db_get_freq()
        },

        db_set_name = function(value){

            self$set_db_name( value )
        },

        db_get_name = function(){
            self$get_db()
        },

        set_data_df =function(){

            self$data_df <- self$to_df ( self$data_ts )
            invisible(self)

        },

        get_data_df = function(){
            return(
                self$data_df
            )
        },

        get_ytd_ts = function(ops='sum'){

            n <- nrow( self$data_df )
            x <- dplyr::arrange( self$data_df, date )
            is_sum <- tolower( trimws( ops) ) =='sum'

            ytd <- numeric( n )
            ytd[1] <- x$value[1]
            j <- 1
            total <- ytd[1]

            for(i in 2:n){

                if(x$yr[i]==x$yr[i-1]){

                    j <- j + 1
                    total <- total + x$value[i]

                    if(is_sum){

                        ytd[i] <- total

                    }else{

                        ytd[i] <- total/j
                    }

                    #cat('i=',i,' j=',j, ' total = ', total, ' total/j ', total/j, "\n")

                }else{

                    ytd[i] <-  x$value[i]
                    j <- 1
                    total <- ytd[i]
                }
            }

            return(
                stats::ts( ytd, start = self$data_start, frequency = self$data_freq )
            )
        },

        get_yearly_ts = function(ops='sum'){

            is_sum <- tolower( trimws( ops) ) =='sum'

            my_sql <- 'select yr, sum(value) as total from my_df group by yr order by yr'

            #cat("is_sum = ", is_sum, "\n")
            if(!is_sum){
                my_sql <- 'select yr, avg(value) as total from my_df group by yr order by yr '
            }

            my_df <- self$data_df
            my_agg <- sqldf::sqldf(my_sql)

            return(
                stats::ts(
                    c(my_agg$total),
                    start = c( my_agg$yr[ 1 ], 1 ),
                    frequency = 1
                )
            )

        },

        set_agg = function(to = 'qtr', ops = 'sum'){

            my_to <- tolower( trimws( to ) )
            is_sum <- tolower( trimws( ops) ) =='sum'

            my_match <- switch( my_to,
                                'mth' = self$MTH,
                                'qtr' = self$QTR,
                                'yr'  = self$YR,
                                'ytd' = self$YTD,
                                'mat' = self$MAT,
                                'maytd' = self$MAYTD

            )

            if(is.null(my_match )){

                self$data_agg_to <- self$NOTKNOWN
                cat('Unknown conversion',to,'\n')
                return(NULL)

            }else{
                self$data_agg_to <- my_match
            }



            if( self$data_freq == 12){

                if( self$data_agg_to == self$MTH){

                    self$data_agg <- self$data_ts

                } else if( self$data_agg_to == self$MQT ){

                    if(is_sum){
                        self$data_agg <- zoo::rollsumr( self$data_ts, k = 3 )
                    }else{
                        zoo::rollmeanr( self$data_ts, k = 3 )
                    }

                }else if( self$data_agg_to == self$MAT ){

                    if(is_sum){
                        self$data_agg <- zoo::rollsumr( self$data_ts, k =12 )
                    }else{
                        self$data_agg <- zoo::rollmeanr( self$data_ts, k = 12 )
                    }

                }else if(self$data_agg_to == self$MAYTD){

                    if(is_sum){

                        self$data_agg <- tg.get_ytd_ts( zoo::rollsumr( self$data_ts, k = 12), ops = 'sum')
                    }else{

                        self$data_agg <- tg.get_ytd_ts( zoo::rollmeanr( self$data_ts, k = 12 ), ops = 'avg')
                    }

                }else if( self$data_agg_to == self$YR ){

                    self$data_agg <- self$get_yearly_ts( ops = ops)

                }else if(self$data_agg_to == self$QTR){

                    if(is_sum){

                        q_sql <- "select yr,qtr,sum(value) as value from m_data group by yr,qtr"

                    }else{

                        q_sql <- "select yr,qtr,avg(value) as value from m_data group by yr,qtr"

                    }

                    m_data <- self$to_df( self$data_ts, 'x' )
                    m_data$qtr <- ceiling( m_data$mth / 3)
                    q_data <- sqldf::sqldf( q_sql )

                    if(nrow(q_data) > 0){
                        self$data_agg <- ts(q_data$value, start = c(q_data$yr[1], q_data$qtr[1]) , frequency = 4)
                    }else{
                        self$data_agg <- NULL
                    }



                }else if( self$data_agg_to == self$YTD){

                    self$data_agg <- self$get_ytd_ts( ops = ops)

                }else{
                    cat('Impossible conversion. You are trying to convert year,qtr or mth to mth. Conversion should be from month>(qtr,yr) or qtr>yr \n')
                    return(NULL)

                }#YTD

            }else if(self$data_freq == 4){

                if( self$data_agg_to == self$QTR){

                    self$data_agg <- self$data_ts

                }else if( self$data_agg_to == self$MAT ){

                    if( is_sum ){
                        self$data_agg <- zoo::rollsumr( self$data_ts, k = 4)
                    }else{
                        self$data_agg <- zoo::rollmeanr( self$data_ts, k = 4)
                    }

                }else if( self$data_agg_to == self$MAYTD ){

                    if( is_sum ){
                        self$data_agg <- tg.get_ytd_ts( zoo::rollsumr( self$data_ts, k = 4), ops = 'sum')
                    }else{
                        self$data_agg <- tg.get_ytd_ts( zoo::rollmeanr( self$data_ts, k = 4), ops='avg')
                    }

                }else if( self$data_agg_to == self$YR ){

                    self$data_agg <- self$get_yearly_ts( ops = ops)

                }else if( self$data_agg_to == self$YTD){

                    self$data_agg <- self$get_ytd_ts( ops = ops)

                }else{
                    cat('Impossible conversion \n')
                    return(NULL)
                }#YTD
            }else if(self$data_freq > 12){

                if( self$data_agg_to == self$MTH){

                }
            }

            invisible(self)
        },#function

        get_agg = function(){
            return(
                self$data_agg
            )
        },

        set_agg_default = function(to = 'qtr', ops = 'sum'){
            self$set_agg( to = to, ops = ops)

            self$data_raw <- self$data_agg
            self$set_data_format(self$data_raw)

            self$set_data_start( start(self$data_raw) )
            self$set_data_frequency( frequency( self$data_raw) )
            self$set_data_ts()
            self$set_data_df()

            invisible(self)

        },
        ### GROWTH FUNCTIONS ###
        get_mm1 = function(){
            if( self$data_freq == 12 ){

                my_growth <- quantmod::Delt( c(self$data_ts),k=1)*100
                self$data_growth <- ts( c(my_growth), start = self$data_start, frequency = self$data_freq)
                return(self$data_growth)

            }else{
                cat("Month to month growth rate not possible. Frequency must be 12\n")
                return(NULL)
            }
        },

        get_mm3 = function(){
            if( self$data_freq == 12 ){

                my_growth <- quantmod::Delt( c(self$data_ts),k=3)*100
                self$data_growth <- ts( c(my_growth), start = self$data_start, frequency = self$data_freq)
                return(self$data_growth)

            }else{
                cat("Three-monthly growth rate not possible. Frequency must be 12\n")
                return(NULL)
            }
        },

        get_mm12 = function(){
            if( self$data_freq == 12 ){

                my_growth <- quantmod::Delt( c(self$data_ts),k=12)*100
                self$data_growth <- ts( c(my_growth), start = self$data_start, frequency = self$data_freq)
                return(self$data_growth)

            }else{
                cat("Year on year monthly growth rate not possible. Frequency must be 12\n")
                return(NULL)
            }
        },

        get_qq1 = function( ops = 'avg'){
            if( self$data_freq == 4 ){

                my_growth <- quantmod::Delt( c(self$data_ts),k=1)*100
                self$data_growth <- ts( c(my_growth), start = self$data_start, frequency = self$data_freq)
                return(self$data_growth)

            }else if(self$data_freq == 12){

                my_data <- self$set_agg( 'qtr', ops = ops )$get_agg()
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat("Quarter to quarter growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }
        },

        get_qq4 = function( ops = 'avg' ){
            if( self$data_freq %in% c(4,12) ){

                my_data <- NULL

                if( self$data_freq == 4){
                    my_data <- self$data_ts
                }else{
                    my_data <- self$set_agg( 'qtr', ops = ops )$get_agg()
                }

                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat("Year on year quarterly growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }
        },

        get_maytdm1 = function( ops = 'avg'){

             if(self$data_freq == 12 ){

                my_data <- self$set_agg( 'maytd', ops = ops )$get_agg()
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 12)
                return( self$data_growth )

            }else{
                cat(" Frequency must be 12 for ytd-ma 1-month % change \n")
                return(NULL)
            }
        },

        get_maytdm12 = function( ops = 'avg'){

            if(self$data_freq == 12 ){

                my_data <- self$set_agg( 'maytd', ops = ops )$get_agg()
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 12)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 12)
                return( self$data_growth )

            }else{
                cat(" Frequency must be 12 for ytd-ma 1-month % change \n")
                return(NULL)
            }
        },

        get_maytdq1 = function( ops = 'avg'){

            if(self$data_freq == 4 ){

                my_data <- self$set_agg( 'maytd', ops = ops )$get_agg()
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else if(self$data_freq == 12){


                my_qtr <- self$set_agg( 'qtr', ops = ops )$get_agg()

                my_data <- tg.get_ytd_ts( my_qtr , ops = ops)
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat(" Frequency must be 12 for ytd-ma 1-month % change \n")
                return(NULL)
            }
        },

        get_maytdq4 = function( ops = 'avg'){

            if(self$data_freq == 4 ){

                my_data <- self$set_agg( 'maytd', ops = ops )$get_agg()
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else if(self$data_freq == 12){


                my_qtr <- self$set_agg( 'qtr', ops = ops )$get_agg()

                my_data <- tg.get_ytd_ts( my_qtr , ops = ops)
                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat(" Frequency must be 12 for ytd-ma 1-month % change \n")
                return(NULL)
            }
        },

        get_yy1 = function( ops = 'sum'){
            if( self$data_freq %in% c(1,4,12) ){

                my_data <- NULL

                if( self$data_freq == 1){
                    my_data <- self$data_ts
                }else{
                    my_data <- self$set_agg( 'yr', ops = ops )$get_agg()
                }

                my_start <- start( my_data )
                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 1)
                return( self$data_growth )

            }else{
                cat("Year on year growth rate not possible. Frequency must be 1 or  4 or 12\n")
                return(NULL)
            }
        },
        get_mat1 = function( ops = 'sum'){

            if( self$data_freq == 12 ){

                my_data <- self$set_agg( 'mat', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else if( self$data_freq == 4 ){

                my_data <- self$set_agg( 'mat', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else{
                cat("Moving total growth rate not possible. Frequency must be 12 for monthly data or 4 for quarterly data\n")
                return(NULL)
            }
        },

        get_mqt1 = function( ops = 'sum'){

            if( self$data_freq == 4 ){

                my_data <- self$set_agg( 'mat', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else if( self$data_freq == 12 ){

                my_qtr <- self$set_agg( 'qtr', ops = ops )$get_agg()
                my_data <- zoo::rollmeanr( my_qtr, k = 4)

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat("Moving total growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }
        },
        get_mat12 = function( ops = 'sum'){
            if( self$data_freq %in% c(4,12) ){

                my_data <- self$set_agg( 'mat', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_k <- ifelse( self$data_freq == 12,12,4)

                my_growth <- quantmod::Delt( c( my_data ), k = my_k)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else{
                cat("Moving total growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }
        },

        get_mat4 = function( ops = 'sum'){
            self$get_mqt4( ops = ops)
        },

        get_mqt4 = function( ops = 'sum'){

            if( self$data_freq == 4 ){

                my_data <- self$set_agg( 'mat', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else if( self$data_freq == 12 ){

                my_qtr <- self$set_agg( 'qtr', ops = ops )$get_agg()
                my_data <- zoo::rollmeanr( my_qtr, k = 4)

                my_start <- start( my_data )

                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )

            }else{
                cat("Moving total growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }

        },



        get_ytd12 = function(ops = 'sum'){
            if( self$data_freq %in% c(4,12) ){

                my_data <- self$set_agg( 'ytd', ops = ops )$get_agg()

                my_start <- start( my_data )

                my_k <- ifelse( self$data_freq == 12,12,4)

                my_growth <- quantmod::Delt( c( my_data ), k = my_k)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq)
                return( self$data_growth )

            }else{
                cat("year todate total growth rate not possible. Frequency must be 4 or 12\n")
                return(NULL)
            }
        },

        get_ytd4 = function(ops = 'sum'){

            if( self$data_freq == 4 ){

                self$get_ytd12( ops = ops )

            }else if( self$data_freq == 12){

                my_qtr <- self$set_agg( 'qtr', ops = ops )$get_agg()

                my_data <- tg.get_ytd_ts( dt = my_qtr, ops = ops )

                my_start <- start( my_data )



                my_growth <- quantmod::Delt( c( my_data ), k = 4)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = 4)
                return( self$data_growth )


            }
        },

        get_ytd1 = function(ops = 'avg'){

            if( self$data_freq %in% c(4,12)){


                my_data <- tg.get_ytd_ts( dt = self$data_ts, ops = ops )

                my_start <- start( my_data )


                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq )
                return( self$data_growth )


            }else{
                cat('Unknown frequency \n')
                return( NULL)
            }
        },

        get_yqt1 = function(ops = 'avg'){

            if( self$data_freq  %in% c(4,12) ){


                my_data <- switch(as.character(self$data_freq),
                                  '4'  = tg.get_ytd_ts( dt = self$data_ts, ops = ops ),
                                  '12' = tg.get_ytd_ts( dt = self$set_agg('qtr', ops = ops)$get_agg(), ops = ops )
                )

                my_start <- start( my_data )


                my_growth <- quantmod::Delt( c( my_data ), k = 1)*100
                self$data_growth <- ts( c(my_growth), start = my_start, frequency = self$data_freq )
                return( self$data_growth )


            }else{
                cat('Unknown frequency \n')
                return( NULL)
            }
        },

        get_growth_df = function( ops = 'avg', select = private$ALL_CODES, select_yr = c(2000,2050)){

            n_select <- nchar(select)

            #get code description
            code_desc <- ''
            SQ <- storedQry::SQ$new( self$db_name )$set_name( 'trends_meta_get_desc' )
            my_desc <- SQ$set_params( list( `@s_code`= toupper(self$data_code)  ) )$qry_exec()
            if(nrow(my_desc) >0 ){
                code_desc <- my_desc$description[1]
            }

            if(self$data_freq == private$frq_MTH  ){

                # n_select is the number of characters in growth code,
                # if < 6, then it likely to be just one growth code
                if( n_select < 6){

                    #cat("I am saving the planet\n")

                    my_select <- toupper(select)

                    my_data <- switch( my_select,

                                       MM1   = self$to_df( self$get_mm1(), 'MM1', T),
                                       MM3   = self$to_df( self$get_mm3(), 'MM3', T),
                                       MM12  = self$to_df( self$get_mm12(), 'MM12', T),
                                       QQ1   = self$to_df( self$get_qq1( ops = ops ), 'QQ1', T),
                                       YTD1   = self$to_df( self$get_ytd1( ops = ops ), 'YTD1', T),

                                       QQ4   = self$to_df( self$get_qq4( ops = ops ), 'QQ4', T),
                                       YY1   = self$to_df( self$get_yy1( ops = ops ), 'YY1', T),
                                       MAT1  = self$to_df( self$get_mat1( ops = ops ), 'MAT1', T),
                                       MQT1 = self$to_df( self$get_mqt1( ops = ops ), 'MQT1', T),

                                       YQT1 = self$to_df( self$get_yqt1( ops = ops ), 'YQT1', T),
                                       MAT12 = self$to_df( self$get_mat12( ops = ops ), 'MAT12', T),
                                       MAT4 = self$to_df( self$get_mat4( ops = ops ), 'MAT4', T),
                                       YTD4  = self$to_df( self$get_ytd4( ops = ops ), 'YTD4', T),

                                       MQT4 = self$to_df( self$get_mqt4( ops = ops ), 'MQT4', T),
                                       YTD12 = self$to_df( self$get_ytd12( ops = ops ), 'YTD12', T),
                                       MAYTDM1 = self$to_df( self$get_maytdm1( ops = ops ), 'MAYTDM1', T),
                                       MAYTDM12 = self$to_df( self$get_maytdm1( ops = ops ), 'MAYTDM12', T)

                    )

                    my_data <- sqldf::sqldf(
                        sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper( select ) ), select_yr[1], select_yr[2])
                    )

                }else{

                    my_mm1  <- self$to_df( self$get_mm1(), 'MM1', T)
                    my_mm3  <- self$to_df( self$get_mm3(), 'MM3', T)
                    my_mm12 <- self$to_df( self$get_mm12(), 'MM12', T)
                    my_qq1  <- self$to_df( self$get_qq1(), 'QQ1', T)

                    my_qq4  <- self$to_df( self$get_qq4(ops = ops), 'QQ4', T)
                    my_yy1  <- self$to_df( self$get_yy1( ops = ops ), 'YY1', T)
                    my_mat1 <- self$to_df( self$get_mat1( ops = ops ), 'MAT1', T)
                    my_mqt1 <-  self$to_df( self$get_mqt1( ops = ops ), 'MQT1', T)

                    my_yqt1 <-  self$to_df( self$get_yqt1( ops = ops ), 'YQT1', T)
                    my_mat12 <- self$to_df( self$get_mat12( ops = ops ), 'MAT12', T)
                    my_mat4 <-  self$to_df( self$get_mat4( ops = ops ), 'MAT4', T)
                    my_ytd1 <-  self$to_df( self$get_ytd1( ops = ops ), 'YTD1', T)

                    my_ytd4 <-  self$to_df( self$get_ytd4( ops = ops ), 'YTD4', T)
                    my_ytd12 <- self$to_df( self$get_ytd12( ops = ops ), 'YTD12', T)
                    my_maytdm1 <- self$to_df( self$get_maytdm1( ops = ops ), 'MAYTDM1', T)
                    my_maytdm12 <- self$to_df( self$get_maytdm1( ops = ops ), 'MAYTDM12', T)

                    my_data <- rbind(
                        my_mm1,   my_mm3,   my_mm12, my_qq1,
                        my_qq4,   my_yy1,   my_mat1, my_mqt1,
                        my_yqt1,  my_mat12, my_mat4, #my_ytd1,
                        my_ytd4, my_ytd12, my_maytdm1, my_maytdm12
                    )

                    my_data <- sqldf::sqldf(
                        sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper( select ) ), select_yr[1], select_yr[2])
                    )

                }

                my_data$data_code <- self$data_code
                my_data$data_desc <- code_desc
                return(my_data)


            } else if( self$data_freq == private$frq_QTR ){

                if( n_select < 6){

                    my_select <- toupper(select)

                    my_data <- switch( my_select,
                                       QQ1   =  self$to_df( self$get_qq1(), 'QQ1', T),
                                       QQ4   = self$to_df( self$get_qq4( ops = ops ), 'QQ4', T),
                                       YY1  = self$to_df( self$get_yy1( ops = ops ), 'YY1', T),
                                       MQT1   = self$to_df( self$get_mqt1( ops = ops ), 'MQT1', T),
                                       MQT4   = self$to_df( self$get_mqt4( ops = ops ), 'MQT4', T),
                                       MAT1   = self$to_df( self$get_mat1( ops = ops ), 'MAT1', T),
                                       MAT4   = self$to_df( self$get_mat4( ops = ops ), 'MAT4', T),
                                       YTD4= self$to_df( self$get_ytd4( ops = ops ), 'YTD4', T),
                                       YTD1= self$to_df( self$get_ytd1( ops = ops ), 'YTD1', T),
                                       MAYTDQ1= self$to_df( self$get_maytdq1( ops = ops ), 'MAYTDQ1', T),
                                       MAYTDQ4= self$to_df( self$get_maytdq4( ops = ops ), 'MAYTDQ4', T)
                    )

                    my_data <- sqldf::sqldf(
                        sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper( select ) ), select_yr[1], select_yr[2])
                    )


                }else{

                    my_qq1 <-self$to_df( self$get_qq1(), 'QQ1', T)
                    my_qq4 <- self$to_df( self$get_qq4(  ops = ops ), 'QQ4', T)

                    my_yy1 <- self$to_df( self$get_yy1( ops = ops ), 'YY1', T)

                    my_mqt1 <- self$to_df( self$get_mqt1( ops = ops ), 'MQT1', T)
                    my_mqt4 <- self$to_df( self$get_mqt4( ops = ops ), 'MQT4', T)

                    my_mat1 <- self$to_df( self$get_mat1( ops = ops ), 'MAT1', T)
                    my_mat4 <- self$to_df( self$get_mat4( ops = ops ), 'MAT4', T)

                    my_ytd1 <- self$to_df( self$get_ytd1( ops = ops ), 'YTD1', T)
                    my_ytd4 <- self$to_df( self$get_ytd4( ops = ops ), 'YTD4', T)

                    my_maytdq1 <- self$to_df( self$get_maytdq1( ops = ops ), 'MAYTDQ1', T)
                    my_maytdq4 <- self$to_df( self$get_maytdq4( ops = ops ), 'MAYTDQ4', T)

                    my_data <- rbind(
                        my_qq1, my_qq4,
                        my_yy1,
                        my_mqt1, #my_mqt4,
                        my_mat4, #my_mat1,
                        my_ytd4, # my_ytd1
                        my_maytdq1, my_maytdq4
                    )

                    my_data <- sqldf::sqldf(
                        sprintf("select * from my_data where name in %s and yr between %s and %s",  beamaUtils::split_str( toupper( select ) ), select_yr[1], select_yr[2])
                    )
                }

                my_data$data_code <- self$data_code
                my_data$data_desc <- code_desc
                return(my_data)


            } else if( self$data_freq == private$frq_YR ){

                my_yy1 <- self$to_df( self$get_yy1( ops = ops ), 'YY1', T)

                my_data <- sqldf::sqldf(
                    sprintf("select * from my_yy1 where name in %s and yr between %s and %s",  beamaUtils::split_str( toupper( select ) ), select_yr[1], select_yr[2])
                )
                my_data$data_code <- self$data_code
                my_data$data_desc <- code_desc
                return( my_data )


            }else {

                ### TO BE IMPLEMENTED
                return( NULL )
            }
        },

        get_agg_df = function( ops = 'avg', select = private$ALL_CODES, select_yr = c(1900,2050) ){


            if(self$data_freq == private$frq_MTH  ){

                my_mth  <- self$to_df( self$data_ts, 'MTH', T )

                my_qtr <- self$to_df( self$set_agg('qtr', ops = ops )$get_agg() , 'QTR', T )

                my_yr  <- self$to_df( self$set_agg('yr', ops = ops )$get_agg() , 'YR', T )
                my_ytd <- self$to_df( self$set_agg('ytd', ops = ops )$get_agg() , 'YTD', T )
                my_mat <- self$to_df( self$set_agg('mat', ops = ops )$get_agg() , 'MAT', T )
                my_maytd <- self$to_df( self$set_agg('mat', ops = ops )$get_agg() , 'MAYTD', T )

                my_data<-  rbind( my_mth, my_qtr, my_yr, my_ytd, my_mat,my_maytd )

                my_data <- sqldf::sqldf(
                    sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper(select ) ), select_yr[1], select_yr[2])
                )

                return(my_data)


            } else if( self$data_freq == private$frq_QTR ){

                my_qtr  <- self$to_df( self$data_ts, 'QTR', T )
                my_yr  <- self$to_df( self$set_agg('yr', ops = ops )$get_agg() , 'YR', T )
                my_ytd <- self$to_df( self$set_agg('ytd', ops = ops )$get_agg() , 'YTD', T )
                my_mat <- self$to_df( self$set_agg('mat', ops = ops )$get_agg() , 'MAT', T )
                my_maytd <- self$to_df( self$set_agg('mat', ops = ops )$get_agg() , 'MAYTD', T )

                my_data <- rbind( my_qtr, my_yr, my_ytd, my_mat, my_maytd )


                my_data <- sqldf::sqldf(
                    sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper(select ) ), select_yr[1], select_yr[2])
                )

                return(my_data)



            } else if( self$data_freq == private$frq_YR ){

                my_data <- self$to_df( self$data_ts, 'YR', T )



                my_data <- sqldf::sqldf(
                    sprintf("select * from my_data where name in %s and yr between %s and %s", beamaUtils::split_str( toupper(select ) ), select_yr[1], select_yr[2])
                )

                return( my_data  )

            }else {

                ### TO BE IMPLEMENTED - daily fx
                #
                # --- MONTH ----

            }

        },

        #' is_growth = plot parameter or it growth
        #' select = MM1:   1 month growth
        #'          MM12: 12 months growth
        #'          MM3:   3 months growth
        #'          QQ1:  1 quarter growth
        #'          QQ4:  4 quarters growth
        #'          YTD12: year to date growth (monthly)
        #'          YTD4:  year to date growth (quarterly)
        #'          MAT1:  moving annual total compared with prev month
        #'          MAT12: moving annual total compared to prev year
        #'          YY1:  yearly growth
        #' ops         = operation to perform : c("sum", "avg")
        #' delta_x     = margins on x-axis in months
        #' delta_y     = margins on y-axis
        #' skale       = scale factor for y-axis
        #' skale_title = lable to go with y-axis scale factor
        #' title       = title of the plot
        #' select_yr   = year filter eg. c(2015,2020)
        #
        plot = function(

            is_growth = FALSE, select = NULL ,
            ops = 'avg', x_delta = c(0,0), y_delta = c(0,0),dp = 1, skale = 1 ,
            skale_title = 'Value', title = NULL, select_yr = NULL,x_breaks = '1 years', x_format='%Y'
            ,strip_txt_size = 12, is_themed = F, caption_txt_size = 4,
            line_col = beamaColours::get_corporate_blue(),
            strip_col = beamaColours::get_blue(),
            strip_fcol = 'white', brexit_mode = FALSE, brexit_mode_line = 0.8,
            smart_labels = SMART_LABELS, title_font_size = 14, show_min_max = T,
            min_max_days = 90,
            return_plot = F, font_text = "Museo 300", font_title = "Museo 500",
            growth_title = NULL, line_size = 1.2


        ){

            require(ggplot2)
            require(magrittr)
            require(ggthemes)

            my_select_yr <- select_yr
            my_select <- select

            if( is.null(select) ){ my_select <- private$ALL_CODES }
            if( is.null(select_yr)) { my_select_yr <- c(1900,2050) }

            my_data <- NULL
            my_ylab <- NULL

            if( is.null( self$data_freq ) ) {
                cat('What meanest thou o sleeper! No data to plot. I am afraid I have to quit...\n')
                return( NULL )
            }

            if(!is_growth) {

                my_data <- self$get_agg_df(ops = ops, select = my_select, select_yr = my_select_yr)


                my_data$value <- my_data$value / skale
                my_ylab <- skale_title

            }else{

                my_data <- self$get_growth_df(ops = ops, select = my_select, select_yr = my_select_yr)


                if(is.null(growth_title)){
                    my_ylab <- "Growth (%)"
                }else{
                    my_ylab <- growth_title
                }

            }

            my_data$smart <- my_data$name

            if( !is.null( smart_labels ) ){

                for( name in names(smart_labels)){

                    my_data$smart[ which( my_data$name == name )] <- smart_labels[[ name ]]

                }
            }

            #return(my_data)
            gmin <- vmin <- NULL
            gmax <- vmax <- NULL


            my_data$data_days <- with(my_data,yr*372+mth*31)


            if( !is.null(self$db_limit$yr) ){

                ### test test test
                #cat('db_limit: yr=',self$db_limit$yr,", mth = ", self$db_limit$mth,"\n")

                # my_data <- dplyr::filter(
                #     my_data, data_days <= beamaUtils::ddays( self$db_limit$yr, self$db_limit$mth, d360=31)
                # )

                ### test test test
                #return( my_data)
            }


            gmin <- my_data %>% dplyr::group_by(name) %>% dplyr::filter( data_days == min(data_days) )
            gmax <- my_data %>% dplyr::group_by(name) %>% dplyr::filter( data_days == max(data_days) )
            gtxt <- rbind(gmin,gmax)



            vmin <-  dplyr::filter(  dplyr::group_by( my_data, name ), value == min( value ) )
            vmax <-  dplyr::filter(  dplyr::group_by( my_data, name ), value == max( value ) )
            vtxt <- rbind(vmin,vmax)

            x_range <- c(min(gmin$date) , max(gmax$date))
            if(!(x_delta[1] == 0)){
                x_min <- min(gmin$date)

                lubridate::month(x_min) <- lubridate::month(x_min) - x_delta[1]
                x_range[1] <- x_min
            }

            if(!(x_delta[2] == 0)){

                x_max <- max(gmax$date)

                lubridate::month(x_max) <- lubridate::month(x_max) + x_delta[2]

                x_range[2] <- x_max
            }

            g <- ggplot(my_data, aes(x = date, y= value)) +
                geom_line( size = line_size, colour = line_col ) +
                facet_wrap(~smart)

            g <- g + xlab("") + ylab( my_ylab )
            if( !is.null( title) ){
                g <- g + ggtitle( title )
            }




            g <- g + geom_point( data=gtxt, aes( x = date, y = value), size=5, colour = line_col)
            g <- g + geom_point( data=gtxt, aes( x = date, y = value), colour = beamaColours::get_pink(),size=3)
            g <- g + geom_text(  data=gtxt, aes( x = date, y = value, label = beamaUtils::set_decimal( value , dp)), vjust= -0.8, hjust = 0.4, size = caption_txt_size, colour= beamaColours::get_pink() )

            g <- g + geom_point( data=vtxt, aes( x = date, y = value ) , size = 3,       colour = beamaColours::get_blue() )
            g <- g + geom_point( data=vtxt, aes( x = date, y = value ) , size = 1.5,     colour = beamaColours::get_gray() )

            if( show_min_max ){

                min_days <- gmin$data_days[ 1 ]
                max_days <- gmax$data_days[ 1 ]

                vmin$min <- abs( vmin$data_days - min_days )
                vmin$max <- abs( vmin$data_days - max_days )

                vmax$min <- abs( vmax$data_days - min_days )
                vmax$max <- abs( vmax$data_days - max_days )

                vmin <- dplyr::filter( vmin, min > min_max_days, max > min_max_days  )
                vmax <- dplyr::filter( vmax, min > min_max_days, max > min_max_days )

                g <- g + geom_text(  data=vmin, aes( x = date, y = value, label = beamaUtils::set_decimal( value, dp) ),vjust= 1.4,hjust=0.6,size= caption_txt_size, colour = beamaColours::get_smooth_colour())
                g <- g + geom_text(  data=vmax, aes( x = date, y = value, label = beamaUtils::set_decimal( value, dp) ),vjust=-0.6,hjust=0.4,size= caption_txt_size, colour = beamaColours::get_smooth_colour())

            }


            g <- g + theme(legend.position="none", strip.text = element_text( size= strip_txt_size ))

            if(is_themed){
                g <- g + theme_igray()
                g <- g + scale_colour_tableau("colorblind10")
                g <- g + theme(
                    strip.background = element_rect(colour = strip_col, fill = strip_col),
                    strip.text.x = element_text(family = font_text, face="plain",colour = strip_fcol, size= strip_txt_size),
                    legend.position = "none",
                    legend.title = element_blank(),
                    text = element_text(family= font_text, face="plain"),
                    plot.title = element_text(family = font_title, face="plain", size= title_font_size)

                )
            }


            g_range <- ggplot_build(g)$layout$panel_ranges[[1]]$y.range

            y_range <- g_range

            #cat("g_range = c(", g_range[1]," , ", g_range[2],")\n")
            #cat("y_delta = c(", y_delta[1]," , ", y_delta[2],")\n")

            if( !( y_delta[1] == 0) ){

                if( g_range[1] < 0 ) {
                    y_range[1] <- g_range[1] + y_delta[1]
                }else{
                    y_range[1] <- g_range[1] - y_delta[1]
                }

            }

            if(!( y_delta[2] == 0)){

                if( g_range[2] < 0 ) {

                    y_range[2] <- g_range[2] - y_delta[2]

                }else{

                    y_range[2] <- g_range[2] + y_delta[2]

                }

            }

            #cat("yrange = c(", y_range[1]," , ", y_range[2],")\n")

            if( ( y_range[1] * y_range[2] ) < 0 ){

                g <- g + geom_hline( yintercept = 0)

            }

            if( !( sum(y_delta) == 0) ) {

                g <- g + ylim( y_range )

            }

            if( !( sum(x_delta) == 0 ) ){

                g <- g + scale_x_date(date_breaks = x_breaks, date_labels = x_format, limits = x_range )

            }else{

                g <- g + scale_x_date(date_breaks = x_breaks, date_labels = x_format )

            }

            if(brexit_mode){

                g <- g + geom_vline( aes(xintercept = as.numeric(as.Date( BREXIT_POINT )) ), colour = beamaColours::get_pink(), linetype = 'dashed', size= brexit_mode_line )

            }
            if( self$brexit_label == T){

                bxl <- self$get_brexit_text()

                #g <- g + geom_text(data = bxl, aes(x = x, y= y, label = label, angle = angle, size = size), colour = beamaColours::get_pink())
                g <- g + annotate(
                    geom = 'text',
                    x = bxl$x, y = bxl$y, label = bxl$label ,
                    color = beamaColours::get_pink(),
                    angle = bxl$angle,
                    size = bxl$size
                )
            }




            print(g)

            if(return_plot){
                return( g )
            }else{

              return(my_data)
            }

        }

        # #### spider ###
        ,plot_spider = function(
            fx=c('mth','qtr','ytd','mat'), k = 12, title= NULL,
            y1 = lubridate::year(Sys.Date())-2, y2=lubridate::year(Sys.Date()) ,
            verbose =FALSE, strip_txt_size = 12, is_themed = T,
            line_col = beamaColours::get_corporate_blue(),
            strip_col = beamaColours::get_blue(),
            strip_fcol = 'white',y_delta=c(0,0),x_delta=c(0,0), title_font_size = 14,
            is_brexit = FALSE, brexit_point = c(2016,6),
            brexit_colour = beamaColours::get_pink(),
            point_colour = beamaColours::get_gray(),
            start_finish = c(

                beamaColours::get_limegreen(),
                beamaColours::get_darkyellow(),
                beamaColours::get_yellow(),
                beamaColours::get_green()
            ),
            font_text = "Museo 300", font_title = "Museo 500",

            show_growth_caps = F,
            caps_x = c(1, 1, -1, -1),
            caps_y = c(1,-1, -1,  1),
            caps_lbl = c('EXPANSION','RECOVERY','CONTRACTION','SLOWDOWN'),
            caps_col = gray.colors(10)[7],
            caps_size = 8
        ){

            require("magrittr")
            require("ggplot2")
            require("ggthemes")

            my_fx <- tolower( match.arg( fx ) )
            frq <- original_frq <- self$data_freq

            my_data <- NULL

            if( (my_fx == 'mth' && frq == 12) || (my_fx == 'qtr' && frq == 4) ){

                my_data <- self$get_data_df()

            }else{

                my_data <- self$get_agg_df( select = my_fx)

                frq <- switch( fx,
                               'mat' = original_frq,
                               'ytd' = original_frq,
                               'qtr' = 4
                )
            }


            data_desc <- NULL
            if( is.null(title)){

                data_desc <- self$data_code

            }else{

                data_desc <- title

            }

            x_label <- NULL
            y_label <- NULL
            my_k <- k

            if( frq == 12 ){

                x_label <- paste0(toupper(fx),' : ' , "1-month % change" )

                if( (k == 1 ) || (k > 12) ){ my_k <- 12 }


                y_label <- paste0(toupper(fx),' : ', my_k , "-month % change" )

            }

            if( frq == 4  ){

                x_label <- paste0( toupper(fx),' : ', "1-quarter % change" )

                if( ( k == 1 ) || (k > 4) ){ my_k <- 4 }


                y_label <- paste0( toupper(fx),' : ', my_k , "-quarter % change" )

            }



            abc <- my_data


            left_shift <- function(x,delta=1){ tp_utils$new()$vec_shift_left(x,delta)}

            abc$mom <- quantmod::Delt( abc$value, k = 1)[ , 1 ] * 100
            abc$yoy <- quantmod::Delt( abc$value ,k = my_k)[ , 1 ] * 100
            abc_len <- nrow( abc )
            abc$slope_y <- numeric( abc_len )
            abc$slope_x <- numeric( abc_len )

            for(i in 2:(abc_len)){

                up <- abc$yoy[i] - abc$yoy[ i - 1 ]
                down <- abc$mom[i] - abc$mom[ i - 1 ]
                abc$slope_y[ i ] <- up /down
                abc$slope_x[ i ] <- down / up

            }

            abc$mome <- left_shift( abc$mom )
            abc$yoye <- left_shift( abc$yoy )



            gdata <-  dplyr::filter(abc, yr >= y1)
            gdata$data_desc <- data_desc
            gdata$lbl <- ""
            xy_scale <- 1
            delta <- 0.2


            gdata <- dplyr::filter(gdata, yr >= y1, yr<= y2)

            gdata$data_days <- with( gdata, yr * 372 + mth * 31  )
            gmin <- dplyr::filter( gdata, !is.na( yoy ))  %>% dplyr::filter( data_days == min( data_days ))
            gmax <- gdata  %>% dplyr::filter( data_days == max( data_days ) )
            gtxt <- rbind( gmin, gmax )

            brexit_df <- NULL

            if(is_brexit){

                brexit_df <- dplyr::filter(gdata, yr == brexit_point[1], mth == brexit_point[ 2 ] )
            }

            g <- ggplot( gdata, aes( x = mom, y = yoy, label = lbl))
            g <- g + facet_wrap( ~ data_desc )
            g <- g + geom_point( colour = beamaColours::get_euris_blue_light(), size = 2 )
            g <- g + geom_hline( yintercept = 0 )  + geom_vline( xintercept = 0)
            g <- g + geom_segment( aes( xend = mome, yend = yoye ), size = 1.0, colour = line_col,arrow=grid::arrow(angle=15, type = "closed", length = grid::unit(0.18, "inches")))
            g <- g + labs( y = y_label, x = x_label )

            g <- g + geom_text( aes( label = paste0( month.abb[ mth ], yr %% 100 ), vjust = -0.8, hjust = 0.5, size = 5))
            g <- g + geom_point( data = gtxt, aes( x = mom, y = yoy), size = 5, colour = line_col )
            g <- g + geom_point( data = gtxt, aes( x = mom, y = yoy, colour = factor( data_days ) ), size = 4 )

            if(is_brexit){
                g <- g + geom_point( data = brexit_df, aes( x = mom, y = yoy ), colour = line_col, size = 5 )
                g <- g + geom_point( data = brexit_df, aes( x = mom, y = yoy ), colour = brexit_colour, size = 4 )
            }



            y_range <- g_range <- ggplot_build(g)$layout$panel_ranges[[1]]$y.range

            if( !( y_delta[1] == 0) ){
                y_range[1] <- g_range[1] - y_delta[1]
            }

            if(!( y_delta[2] == 0)){
                y_range[2] <- g_range[2] + y_delta[2]
            }

            if( !( sum(y_delta) == 0) ) {
                g <- g + ylim( y_range )
            }

            x_range <- g_range <- ggplot_build(g)$layout$panel_ranges[[1]]$x.range

            if( !( x_delta[1] == 0) ){
                x_range[1] <- g_range[1] - x_delta[1]
            }

            if(!( x_delta[2] == 0)){
                x_range[2] <- g_range[2] + x_delta[2]
            }

            if( !( sum(x_delta) == 0) ) {
                g <- g + xlim( x_range )
            }

            if(is_themed){
                g <- g + theme_igray()
                g <- g + scale_colour_manual( values = start_finish)
                g <- g + theme(
                    strip.background = element_rect(colour = strip_col, fill = strip_col),
                    strip.text.x = element_text(family = font_text, face="plain",colour = strip_fcol, size= strip_txt_size),
                    legend.position = "none",
                    legend.title = element_blank(),
                    text = element_text(family= font_text, face="plain"),
                    plot.title = element_text(family = font_title, face="plain", size= title_font_size)

                )
            }

            if(show_growth_caps){

                g <- g + annotate(
                    'text',
                    x = caps_x,
                    y = caps_y,
                    label = caps_lbl,
                    size = caps_size,
                    colour = caps_col
                )

            }

            print( g )

            if( verbose ) {  return( abc )}
        }



        #### spider ends ###

    ),
    private = list(

        #aggregate fxns
        SUM =1, AVG=2,

        frq_MTH = 12, frq_QTR = 4, frq_YR = 1, frq_DAILY = 270,
        frqs = c(1,4,12,270),

        #growth rates
        MM1 =1,MM3=2,MM12=3, QQ1=4, QQ4=5,YY1=6,MAT1=7,MQT1=8,MQT4=9, YTD12=10, YTD4=11, NOTHING=12,

        #plot constants
        LINE_SIZE = 1.1,
        LINECOLOUR = beamaColours::get_line_colour(),
        SMOOTHCOLOUR = beamaColours::get_pink(),
        ALL_CODES = 'MAT,MTH,QTR,YR,YTD,MAT1,MAT4,MAT12,MM1,MM3,MM12,QQ1,QQ4,YTD1,YTD4,YTD12,YY1,MQT1,MQT4'

    )
)


### NON CLASS ITEMS

#' only for internal use
#' run a query on local persistent data store

tg.run_sql = function(qry){
    return(sqldf::sqldf( qry ,dbname =  'R:/shiny/beama/bmonitor/bss.sqlite'))
}

tg.split_str <- function (s = "CHAY,CHAW,D7BT"){

    return(gsub(",", "','", s))
}

tg.get_db <- function(src='trends'){

    my_db <- switch(src,
                    trends = 'R:/shiny/beama/bmonitor/bss.sqlite',
                    indx = 'R:/packages/bindices/beama_indices.sqlite',
                    fx = 'R:/packages/beamafx/inst/extdata/beamafx.sqlite',
                    btrends='R:/packages/btrends/btrends.sqlite'
    )
    return(my_db)
}

tg.get_code_data <- function(code='CHAW', db = 'trends'){
    my_db <- tg.get_db( db )
    return(
        storedQry::SQ$new( db= my_db )$set_name('get_code_data')$set_params( list(`@s_code` = code ))$qry_exec()
    )
}

tg.get_data <- function(code="CHAW,CHAY",y1=1990,y2=2020,m1=1,m2=12, d1=0,d2=0 ,db='trends', basis='2010=100', fx='m', op='SUM',...){

    #code="m_elec,m_mech";y1=1990;y2=2020;m1=1;m2=12; d1=0;d2=0 ;db='trends'; basis='2010=100'; fx='m'
    my_data <- NULL
    my_db <- tolower(db)# my_db <- 'indx';code='m_elec'

    dd1 <- ( y1 * 12 + m1) * 31 + d1
    dd2 <- ( y2 * 12 + m2) * 31 + d2

    if( my_db == 'trends'){

        qry_name <- paste0( 'trends_get_data_', fx)
        my_code <- tg.split_str( toupper( code ) )
        SQ <- storedQry::SQ$new( tg.get_db( db ) )$set_name( qry_name )
        my_qry <- SQ$set_params(
            list(
                `@s_code`= my_code, `@i_y1`= dd1  ,`@i_y2`= dd2, `@i_op` = op
            )
        )
        #cat('qry = ', my_qry$params_replace(),'\n')

        my_data <- my_qry$qry_exec()

        #cat('rows = ', nrow(my_data ),"\n")





    }

    if( my_db == 'indx'){

        SQ <- storedQry::SQ$new( tg.get_db( my_db ) )$set_name('beama_index_get_trends')
        my_data <- SQ$set_params(
            list(
                `@i_index_name`= beamaUtils::split_str(code), `@s_index_base_to`= basis,
                `@i_y1`=y1  ,`@i_y2`=y2
            )
        )$qry_exec()

        #cat('qry = ', my_qry$params_replace(),'\n')
        #my_data <- my_qry



    }

    return( my_data )
}

tg.sync_desc <- function(code, description, db = tg.get_db( 'trends' )){


    #first update the meta table
    SQ <- storedQry::SQ$new( db )$set_name( 'trends_meta_update_desc' )
    my_qry <- SQ$set_params(
        list(
            `@s_data_code`=code, `@s_data_desc`= description
        )
    )$qry_exec()

    #then update table
    SQ <- storedQry::SQ$new( my_db )$set_name( 'trends_data_update_desc' )
    my_qry <- SQ$set_params(
        list(
            `@s_data_code`=code, `@s_data_desc`= description
        )
    )$qry_exec()


}

tg.get_unit <- function(code, db = tg.get_db( 'trends' ) ){



    SQ <- storedQry::SQ$new( db )$set_name( 'trends_meta_get_unit' )
    my_unit <- SQ$set_params(
        list(
            `@s_code`= code
        )
    )$qry_exec()

    if(nrow( my_unit ) > 0){

        return( my_unit$unit)
    }

    return('')

}


tg.plot_trends<- function(

    code = 'CHAW', y1 = 2013, y2 = 2020, dp = 1,
    grp = FALSE,title = "", lgpos = list( x=0.5, y=0.5, ylab= NULL ),
    add_intercept = FALSE, verbose = FALSE, xaxis_fmt="", xaxis_prd="years", scale=1, is_themed=FALSE,
    y_zero = FALSE, y_manual = c(0,0), strip_txt_size = 12,line_col = beamaColours::get_corporate_blue(),
    strip_col = beamaColours::get_blue(), strip_fcol = 'white', db='trends', fx = 'm',op='SUM', x_delta =c(0,0), y_delta = c(0,0),
    line_size = 1.3, geom_txt_size = 5, geom_txt_col = beamaColours::get_pink(),
    select = NULL, title_font_size =14, #'MAT1,MAT12,MM1,MM12,MM3,QQ1,QQ4,YTD12,YTD4,YY1'
    font_text = "Museo 300", font_title = "Museo 500"

){

    require(ggthemes)
    require(magrittr)
    require(ggplot2)

    ###
    #code='bbt_combined,bbt_beama,bbt_ons'; plot_type = "tracker";scale=1;k=12;db='trends';fx='m'
    #y1=2013;y2=2020;grp=FALSE;title="";y_zero = FALSE; y_manual = c(0,100);grp = FALSE
    #add_intercept=FALSE;verbose=FALSE;xaxis_fmt="";xaxis_prd="years";scale=1;smooth=FALSE

    my_code <- toupper( code )
    my_ylab <- NULL
    my_data <- NULL
    my_wrap <- c('data_desc')

    if(!is.null( select )){

        my_data <- tg.get_growth_data(code = code, select = select, select_yr = c(y1,y2))
        my_data <- dplyr::filter(my_data,yr >= y1, yr<= y2)
        my_ylab <- 'Growth (%)'
        my_wrap <- c('data_desc', 'smart')

    }else{

        my_data <- tg.get_data( code = my_code, y1 = y1, y2 = y2, db = db, fx = fx, op = op )
        my_wrap <- c('data_desc', 'data_unit')
        my_ylab <- lgpos$ylab

        if( is.null(lgpos$ylab) ){

            my_ylab <- ""

        }
    }

    #return(my_data)


    my_data_count <- nrow(my_data)
    if( my_data_count == 0){cat("Aborting process: 0 records\n"); return(NULL)}

    if(is.null( my_data$date) ){
        my_data$date <- as.Date( sprintf("%s-%s-01", my_data$yr, my_data$mth))
    }

    g <- NULL
    if(!grp){


        my_data$data_days <- my_data$yr*372+my_data$mth*31

        gmin <- my_data %>% dplyr::group_by(data_desc) %>% dplyr::filter(data_days==min(data_days))
        gmax <- my_data %>% dplyr::group_by(data_desc) %>% dplyr::filter(data_days==max(data_days))
        gtxt <- rbind(gmin,gmax)

        x_range <- c(min(gmin$date) , max(gmax$date))

        if(!(x_delta[1] == 0)){
            x_min <- min(gmin$date)



            lubridate::month(x_min) <- lubridate::month(x_min) - x_delta[1]
            x_range[1] <- x_min
        }

        if(!(x_delta[2] == 0)){

            x_max <- max(gmax$date)

            lubridate::month(x_max) <- lubridate::month(x_max) + x_delta[2]

            x_range[2] <- x_max
        }

        g <- ggplot(my_data,aes(x=date,y=value))
        g <- g + geom_line(colour= beamaColours::get_corporate_blue(),stat = "identity",size= line_size)
        g <- g + facet_wrap( my_wrap)

        g <- g + geom_point(data=gtxt, aes(x=date, y=value),size=5,colour=line_col)
        g <- g + geom_point(data=gtxt, aes(x=date, y=value,colour=factor(data_days)),size=4)
        g <- g + geom_text( data=gtxt, aes(x=date, y=value,label= beamaUtils::set_decimal( value,dp)),vjust=-0.8,hjust=0.4,size=geom_txt_size ,colour= geom_txt_col)
        g <- g + theme(legend.position="none", strip.text = element_text( size = strip_txt_size ))



        g_range <- ggplot_build(g)$layout$panel_ranges[[1]]$y.range

        y_range <- g_range

        #cat("grange = c(", g_range[1]," , ", g_range[2],")\n")
        #cat("ydelta = c(", y_delta[1]," , ", y_delta[2],")\n")

        if( !( y_delta[1] == 0) ){

            if( g_range[1] < 0 ) {
                y_range[1] <- g_range[1] + y_delta[1]
            }else{
                y_range[1] <- g_range[1] - y_delta[1]
            }

        }

        if(!( y_delta[2] == 0)){
            if( g_range[2] < 0 ) {
                y_range[2] <- g_range[2] - y_delta[2]
            }else{
                y_range[2] <- g_range[2] + y_delta[2]
            }
        }

        if( !( sum(y_delta) ==0) ) {
            g <- g + ylim( y_range )
        }

        #cat("yrange = c(", y_range[1]," , ", y_range[2],")\n")

        if( (y_range[1]*y_range[2]) <0 ){
            g <- g + geom_hline(yintercept = 0)
        }


        if( !( sum(x_delta) == 0 ) ){
            g <- g + xlim( x_range )
        }

        g <- g + theme( legend.position="none" )

    }else{
        g <- ggplot(my_data,aes(x=date,y=value,colour=data_desc))
        g <- g + geom_line(aes(group=code_desc),size= line_size)
        g <- g+ theme(

            legend.position = c(lgpos$x, lgpos$y),
            legend.background = element_rect(fill = NA, colour = NA),#lgpos$fill
            legend.title=element_blank(),
            text = element_text(12),
            legend.position = "bottom"
        )

    }

    g <- g + labs(title=title,x="", y = my_ylab )

    if(add_intercept){
        g <- g + geom_hline(aes(yintercept=0))
    }

    if(is_themed){
        g <- g + theme_igray()
        g <- g + scale_colour_tableau("colorblind10")
        g <- g + theme(

            strip.background = element_rect(colour = strip_col, fill = strip_col),
            strip.text.x = element_text(family = font_text, face="plain",colour = strip_fcol, size = strip_txt_size),

            legend.title = element_blank(),
            legend.position ="none",
            text = element_text( family = font_text, face="plain"),
            plot.title = element_text( family = font_title, face="plain", size = title_font_size)

        )
    }



    print(g)
    if(verbose) {   return(my_data) }
}

tg.get_agg_data <- function(
    code='m_elec,k646', ops = 'avg',
    select = 'MAT,MTH,QTR,YR,YTD',
    select_yr = c(2010,2020),
    meta_info = NULL,
    db = NULL
){

    #code <- 'bbt_combined,bbt_total_ins,bbt_total_ene,bbt_total_wel'; select='MAT'; select_yr = c(2017,2017)
    if( is.null( code )){ cat("Code is empty. Aborting ...\n"); return(NULL)}

    my_codes <- code
    my_split <- tolower ( strsplit(my_codes,",")[[1]] )
    my_n_codes <- length(my_split)
    my_df <- NULL

    if( my_n_codes > 0){

        my_df <- tg$new( my_split[1], db_name = db )$get_agg_df( ops = ops, select = select, select_yr = select_yr)
        my_df$code <- my_split[1]

        if( my_n_codes > 1){
            for(j in 2: my_n_codes ){
                #j = 2
                my_sub_df <- tg$new( my_split[ j ], db_name = db )$get_agg_df( ops = ops, select = select, select_yr = select_yr)
                my_sub_df$code <- my_split[ j ]
                my_df <- rbind ( my_df, my_sub_df )

            }
        }

    }else{
        cat("No codes supplied. Aborting ....\n")
        return( NULL )
    }

    my_df$smart <- my_df$name
    for( name in names(SMART_LABELS)){

        my_df$smart[ which( my_df$name == name )] <- SMART_LABELS[[ name ]]

    }

    my_meta <- meta_info
    if( is.null( meta_info )){
        my_meta <- tp_utils$new( db_name = db )$run_sql(
            sprintf(
                "select data_code as code, data_desc from trends_meta where lower(data_code) in %s",
                tolower(
                    beamaUtils::split_str( my_codes )
                )
            )
        )
    }

    my_meta$code <- tolower( my_meta$code )


    return(
        dplyr::left_join( my_df ,  my_meta, by = "code" )
    )
}

tg.get_growth_data <- function(
    code='m_elec,k646', ops = 'avg',
    select = 'MAT1,MQT1,MAT12,MAT4,MM1,MM12,MM3,QQ1,QQ4,YTD1,YTD12,YTD4,YY1',
    select_yr = c(2010,2020),
    db = NULL
){

    #code <- "m_elec"

    my_codes <- code
    my_split <- strsplit(my_codes,",")[[1]]
    my_df <- NULL
    my_codes_n <- length( my_split )

    if( my_codes_n > 0){

        my_df <- tg$new( my_split[1], db_name = db )$get_growth_df( ops = ops, select = select, select_yr = select_yr)

        if( my_codes_n > 1){
            for(j in 2:my_codes_n ){
                my_sub_df <- tg$new( my_split[ j ], db_name = db  )$get_growth_df( ops = ops, select = select, select_yr = select_yr)
                my_df <- rbind (my_df, my_sub_df)
            }
        }

    }else{
        cat("No codes supplied. Aborting ....\n")
        return( NULL )
    }

    my_df$smart <- my_df$name
    for( name in names(SMART_LABELS)){

        my_df$smart[ which( my_df$name == name )] <- SMART_LABELS[[ name ]]

    }


    return(my_df)
}

tg.sync_currency <- function(src_code = 'USD', dst_code ='USDM', yr =1980, db = tg.get_db( 'trends' ) ){

    cat('Syncing started ',src_code,' ...\n')
    SQ <- storedQry::SQ$new( db )$set_name( 'trends_data_sync_daily_to_month' )
    my_upd <- SQ$set_params(
        list(
            `@s_src_code` = toupper(src_code),
            `@s_dst_code` = toupper(dst_code),
            `@i_yr` = yr
        )
    )$qry_exec()



    cat('All done - syncing completed !!!\n')
}


tg.sync_currencies <- function( yr = lubridate::year(Sys.Date()), db = tg.get_db( 'trends' ) ){

    tg.sync_currency('USD','USDM', yr = yr)
    tg.sync_currency('EUR','EURM', yr = yr)
    tg.sync_currency('JPY','JPYM', yr = yr)
    tg.sync_currency('CNY','CNYM', yr = yr)
    tg.sync_currency('AUD','AUDM', yr = yr)
    tg.sync_currency('INR','INRM', yr = yr)
    tg.sync_currency('BRLM','BRLM', yr = yr)
    tg.sync_currency('TDI-FTSE-100','FTSEM', yr = yr)

    SQ <- storedQry::SQ$new( db )$set_name("trends_update_periods")$qry_exec()
}

tg.get_info <- function(q='ABMI',is_code = F, is_link = F, db = tpu.get_db() ){

    qry <- paste0("select data_code,data_desc,data_frq from trends_meta where data_desc like '%",q,"%'")
    if(is_code){
        qry <- paste0("select * from trends_meta where data_code like '%",q,"%'")
    }

    if(is_link){
        qry <- paste0("select data_code,data_desc,data_src,data_src_url from trends_meta where data_code in ",beamaUtils::split_str(q) )

    }

    my_data <- tp_utils$new( db )$run_sql( qry )

    return(my_data)
}
#tg.get_info('PG-BEAMA',db = PG_DB,is_code=T)
#tg.get_info(is_link = T)
#tg.get_info(is_code = T)

tg.goto_src <- function(q = 'ABMI'){
    #q = "J5EK"
    qry <- sprintf("select data_src_url from trends_meta where lower(data_code) = '%s'", tolower(trimws(q)) )
    my_data <- tp_utils$new( tpu.get_db() )$run_sql( qry )

    if( nrow(my_data) > 0 ){

        my_link <- my_data$data_src_url[1]

        if(! (is.na(my_link) || is.null(my_link)) ){
            if( nchar( my_link ) > 5){

                cat('Going to source ...', my_link,'\n')
                utils::browseURL( my_link )

            }else{

                cat(sprintf('Life is too short but %s link is really SHORT. Bailing out ....\n', my_link))
            }
        }else{

            cat(sprintf('No link for code %s. Bailing out ....\n',q))
        }
    }else{

        cat('Ghost link! Bailing out ....\n')

    }

}

tg.get_group_links <- function(grp){

    tg.get_info( tp_data$new( grp )$get_group(T) , is_link = T)

}

tg.get_brexit_soup_data <- function(){
    my_data <- tp_utils$new()$run_sql( "select * from brexit_soup where x not null" )
    return(my_data)
}

tg.get_ytd_ts <- function(dt = NULL, ops='sum'){

    if( is.null(dt) || !is.ts( dt ) ){
        cat('Supply data not time series \n')
        return(NULL)
    }

    my_start <- stats::start( dt )
    my_freq <- stats::frequency( dt )
    my_data <- tp_utils$new()$to_df( dt )

    n <- nrow( my_data )
    x <- dplyr::arrange( my_data, date )

    is_sum <- tolower( trimws( ops) ) =='sum'

    ytd <- numeric( n )
    ytd[1] <- x$value[1]
    j <- 1
    total <- ytd[1]

    for(i in 2:n){

        if(x$yr[i]==x$yr[i-1]){

            j <- j + 1
            total <- total + x$value[i]
            ytd[i] <- ifelse( is_sum, total, total/j)
            #cat('i=',i,' j=',j, ' total = ', total, ' total/j ', total/j, "\n")

        }else{

            ytd[i] <-  x$value[i]
            j <- 1
            total <- ytd[i]
        }
    }

    return(
        stats::ts( ytd, start = my_start, frequency = my_freq )
    )
}
eamoakohene/beamaTrends documentation built on May 15, 2019, 7:25 p.m.