*! gcmodel 0.5.3 2009-05-25 scott long
*   - minor formatting

//  specify the rhs variables and the levels of base value
//  for the variables in the model.

*!? DO: remove space in front of globals
*!? DO: does this need the estimation sample??
*!? DO: check if variables are in model
*!? DO: verify that lin squ and cube vars are not in varlist

capture program drop gcmodel
program define gcmodel, rclass

    version 9

//  CHECK IF GLOBALS ARE DEFINED

    gc_checksetup
    local error = r(error)
    if `error'==1 {
        exit
    }

//  DECODE OPTIONS

    syntax [varlist(default=none)]  /// RHS variables used in x()
        [if] [in]                   /// select sample for means
        [ ,                         ///
        /// adjust for squares and cubics
        LINear(varlist)             /// linear terms (include in varlist)
        SQUared(varlist)            /// squared terms (not in varlist)
        CUBed(varlist)              /// cubic terms (not in varlist)
        /// how to compute means
        svy                         /// use svy means
        esample                     /// use e(sample) to compute stats
        ///
        Details                     /// show details
        debug                       /// show debugging output
        DIGits(integer 3)           /// rounding digits in strings for x()
        Reset                       /// reset globals
        label(string)               /// label for this model
        ]

    local q "qui"
    if "`debug'"=="debug" {
        local q ""
    }

//  RESET GLOBALS

    if "`reset'"=="reset" {
        gcreset, gcmodel
    }

//  GLOBALS WITH RHS VARIABLES FOR EACH GROUP AND NOINT MODEL

    local rhsgr1    "$gr1var"
    local rhsgr0    "$gr0var"
    local rhsnoint  "$grpvar"

//  Turn label into global variable

    global modellabel "" // reset label
    if "`label'"!="" {
        global modellabel "`label'"
    }

//  CHECK QUADRATIC

    * verify if same variables match across options
    local nlin : word count `linear'
    local nsqu : word count `squared'
    local ncub : word count `cubed'
    local nvar : word count `varlist'
*di "nlin: `nlin'" di "nsqu: `nsqu'" di "ncub: `ncub'" di "nvar: `nvar'"

    if `nlin'!=0 {

        if `nlin'!=`nsqu' {
            di in red "# of linear and squared variables don't match."
            exit
        } // linear
        if `ncub'!=0 {
            if `ncub'!=`nsqu' {
                di in red "# of cubed and squared variables don't match."
                exit
            }
        } // cubic

    } // if nlin option was used

//  SAMPLE TO USE

    if "`debug'"=="debug" {
        if "`if'"!="" {
            di "IS IF:>`if'<"
        }
        if "`in'"!="" {
            di "IS IN:>`in'<"
        }
    }

    tempvar sampis
    if "`esample'"=="" { // don't use e(sample)
        qui gen `sampis' = 1 `if' `in'
    }
    else {
        qui gen `sampis' = e(sample) `if' `in'
    }

//  CREATE XIS LIST

    * locals to hold x() strings
    local xis ""
    local xismn0 ""
    local xismn1 ""
    local xisgr0 ""
    local xisgr1 ""
    local xisgr0mn0 ""
    local xisgr1mn1 ""

    * get globals information about groups
    local grpvar "$grpvar"    // name of group variable
    local gr1var "$gr1var"    // name of group 1
    local gr0var "$gr0var"    // name of group 0

    * create global with x() info for variables defining groups
    global gr1 "`gr1var'=1"
    global gr0 "`gr0var'=1"
    global grp "`grpvar'=1"

//  CREATE X() INFO BY LOOPING THROUGH VARIABLES

    * if no variables, dummy out globals
    if "`varlist'"=="" {
/*
RHS variables set to grand means:
   $xallmng:       articles=7.050
   $xgr0mng:
   $xgr1mng:
RHS variables set to group 0 means:
   $xallmn0:       articles=7.415
   $xgr0mn0:
   $xgr1mn0:       m1articles=7.415
RHS variables set to group 1 means:

   $xallmn1:       articles=6.829
   $xgr0mn1:       f0articles=6.829
   $xgr1mn1:
*/
        global xallmng " "
        global xgr0mng " " // ?
        global xgr1mng " " // ?
        global xallmn0 " "
        global xallmn1 " "
        global xgr0mn0 " " // ?
        global xgr0mn1 " "
        global xgr1mn1 " " // ?
        global xgr1mn0 " "
        di in red "no variables specified in varlist."
        exit
    }

    * if variables, create strings setting variables to means
    tempname mn
    local ivar = 0 // count variables processed including linear
    local ilinear = 0 //

    foreach v in `varlist' `linear' { // loop through varlist and linear
        local ++ivar

        * grand non-svy means
        if "`svy'"=="" {
            `q' sum `v' if `sampis'
            local grandmn = r(mean)
        }
        * grand svy means
        else {
            `q' svy: mean `v' if `sampis'
            mat `mn' = e(b)
            local grandmn = `mn'[1,1]
        }
        * round the means
        local grandmn = string(`grandmn',"%9.`digits'f")

        * within group means
        foreach grp in 0 1 { // loop over groups
            * within group non-svy mean
            if "`svy'"=="" {
                `q' sum `v' if `sampis' & `grpvar'==`grp'
                local gr`grp'mn = r(mean)

            }
            * within group svy means
            else {
                `q' svy: mean `v' if `sampis' & `grpvar'==`grp' // by group
                mat `mn' = e(b)
                local gr`grp'mn = `mn'[1,1]
            }
            * round the means
            local gr`grp'mn = string(`gr`grp'mn',"%9.`digits'f")
        } // foreach grp loop

        if `ivar'<=`nvar' { // if current var is from linear list
            * x() non-interaction model with grand mean
            local xis "`xis' `v'=`grandmn'"
            local rhsnoint "`rhsnoint' `v'"
*di "** ivar=`ivar' rhsnoint: `rhsnoint'"
           * non-interaction model using group 0 means
            local xismn0 "`xismn0' `v'=`gr0mn'"
            * non-interaction model using group 1 means
            local xismn1 "`xismn1' `v'=`gr1mn'"

            foreach grp in 0 1 {
                * prefix for group g interaction variables
                local nm "`gr`grp'var'"
                * use grand means with interactions
                local xisgr`grp' "`xisgr`grp'' `nm'`v'=`grandmn'"
                * use group means with interactions
                local xisgr`grp'mn`grp' "`xisgr`grp'mn`grp'' `nm'`v'=`gr`grp'mn'"
                local newvarnm "`gr`grp'var'`v'"
                local rhsgr`grp' "`rhsgr`grp'' `newvarnm'"
            }
            *   across group means
            local xisgr0mn1 "`xisgr0mn1' `gr0var'`v'=`gr1mn'"
            local xisgr1mn0 "`xisgr1mn0' `gr1var'`v'=`gr0mn'"
        } // <=`nvar' so does not requied treatment of squared etc.

        * logic is, if var # is gt # of variables in varlist
        * it must be a quadratic term

        if `ivar'>`nvar' { // if current var is from linear list
            local ++ilinear // which linear term is it?

            if `nsqu'>0 { // there are squared term

                local vsq : word `ilinear' of `squared' // squared var nm
                local grandmn2 = `grandmn'^2
                local gr0mn2 = `gr0mn'^2
                local gr1mn2 = `gr1mn'^2
                local grandmn2 = string(`grandmn2',"%9.`digits'f")
                local gr0mn2 = string(`gr0mn2',"%9.`digits'f")
                local gr1mn2 = string(`gr1mn2',"%9.`digits'f")
                * x() non-interaction model with grand mean
                local xis "`xis' `vsq'=`grandmn2'"
                * non-interaction model using group 0 means
                local xismn0 "`xismn0' `vsq'=`gr0mn2'"
                * non-interaction model using group 1 means
                local xismn1 "`xismn1' `vsq'=`gr1mn2'"
                local rhsnoint "`rhsnoint' `vsq'"
*di "with square: ivar=`ivar' rhsnoint: `rhsnoint'"

                foreach grp in 0 1 {
                    * prefix for group g interaction variables
                    local nm "`gr`grp'var'"
                    * use grand means with interactions
                    local xisgr`grp' "`xisgr`grp'' `nm'`vsq'=`grandmn2'"
                    * use group means with interactions
                    local xisgr`grp'mn`grp' "`xisgr`grp'mn`grp'' `nm'`vsq'=`gr`grp'mn2'"
                    local newvarnm "`nm'`vsq'"
                    local rhsgr`grp' "`rhsgr`grp'' `newvarnm'"
                }

                *   across group means
                local xisgr0mn1 "`xisgr0mn1' `gr0var'`vsq'=`gr1mn2'"
                local xisgr1mn0 "`xisgr1mn0' `gr1var'`vsq'=`gr0mn2'"

            } // squared

            if `ncub'>0 { // there are cubed terms
                local vcu : word `ilinear' of `cubed' // name of squared var
                local grandmn3 = `grandmn'^3
                local gr0mn3 = `gr0mn'^3
                local gr1mn3 = `gr1mn'^3
                local grandmn3 = string(`grandmn3',"%9.`digits'f")
                local gr0mn3 = string(`gr0mn2',"%9.`digits'f")
                local gr1mn3 = string(`gr1mn2',"%9.`digits'f")
                * x() non-interaction model with grand mean
                local xis "`xis' `vcu'=`grandmn3'"
                * non-interaction model using group 0 means
                local xismn0 "`xismn0' `vcu'=`gr0mn3'"
                * non-interaction model using group 1 means
                local xismn1 "`xismn1' `vcu'=`gr1mn3'"
                local rhsnoint "`rhsnoint' `vcu'"

                foreach grp in 0 1 {
                    * prefix for group g interaction variables
                    local nm "`gr`grp'var'"
                    * use grand means with interactions
                    local xisgr`grp' "`xisgr`grp'' `nm'`vcu'=`grandmn3'"
                    * use group means with interactions
                    local xisgr`grp'mn`grp' "`xisgr`grp'mn`grp'' `nm'`vcu'=`gr`grp'mn3'"
                    local newvarnm "`stem`grp''`vcu'"
                    local rhsgr`grp' "`rhsgr`grp'' `newvarnm'"
                }
                *   across group means
                local xisgr0mn1 "`xisgr0mn1' `gr0var'`vcu'=`gr1mn3'"
                local xisgr1mn0 "`xisgr1mn0' `gr1var'`vcu'=`gr0mn3'"

            } // cubed

        } // if variable is from set of quadratic terms

    } // foreach v in varlist + linear

//  CREATE GLOBALS WITH X() INFORMATION

    * global means for non interaction variables
    global xallmng      "`xis'"
    * group means for non interaction variables
    global xallmn0   "`xismn0'"
    global xallmn1   "`xismn1'"
    * global means for interaction variables
    global xgr0mng    "`xisgr0'"
    global xgr1mng    "`xisgr1'"
    * group means for interaction variables
    global xgr0mn0 "`xisgr0mn0'"
    global xgr1mn1 "`xisgr1mn1'"
    global xgr0mn1 "`xisgr0mn1'"
    global xgr1mn0 "`xisgr1mn0'"
    * gdxis2 0.1.3
    global rhsgr1 "`rhsgr1'"
    global rhsgr0 "`rhsgr0'"
    global rhsnoint "`rhsnoint'"
    global rhsinteract "`rhsgr0' `rhsgr1'"

//  DETAILS

    if "`details'"=="details" {
*        di _new "Summary of global variables"
        gcglobals, gcmodel
    }
end
exit

//  History

* gdxis3 0.3.0 2008-04-10 > esample is now an option rather than the default.
* gcspecify 0.1.2 2008-07-11 sometimes not computing means
* gcspecify 0.1.1 2008-06-24 revise global names
* gcspecify 0.1.0 2008-06-18
* gcmodel 0.5.1 2009-05-24 jsl
*   - rhsintact to rhsinteract
* gcmodel 0.5.0 2009-05-22 #2pass some missing globalss
* gcmodel 0.5.0 2009-05-22 #1pass