 %MACRO R0312I1M(INP=, IND=, OUTDATA=, IDVAR=, KEEPVAR=, SEDITS=,
                 DATE_ASOF=, FMNAME=, AGEFMT=, SEXFMT=, DF=1, 
                 AGESEXMAC=AGESEXV4, EDITMAC=R03EDIT1, 
                 LABELMAC=R02X78L1, HIERMAC=R02X78H1, 
                 MULTCCMAC=R02X78M2, SCOREMAC=SCOREVAR);

 %**********************************************************************
 * R0312I1M creates RXHCC and score variables for each person present
 * in the user-provided PERSON file.
 * If a person has at least one diagnosis in user-provided DIAG file 
 * then RXHCCs are created, otherwise RXHCCs are set to 0.
 * Score variables are created using coefficients from 8 final models:
 * 5 continuing enrollee and 3 new enrollee models.
 *
 * Assumptions about input files:
 *   - both files are sorted by person ID
 *   - person level file has the following variables:
 *     :&IDVAR  - person ID variable (it is a macro parameter)
 *     :DOB     - date of birth
 *     :SEX     - sex
 *     :OREC    - original reason for entitlement
 *     :ESRD    - end stage renal disease 
 *     
 *   - diagnosis level file has the following vars:
 *     :&IDVAR  - person ID variable (it is a macro parameter)
 *     :DIAG    - diagnosis
 *
 * Parameters:
 *     INP       - input person dataset
 *     IND       - input diagnosis dataset
 *     OUTDATA   - output dataset
 *     IDVAR     - name of person id variable (HICNO for medicare data)
 *     KEEPVAR   - variables kept in the output dataset
 *     SEDITS    - a switch that controls whether to perform edits 
 *                 on ICD9: 1-YES, 0-NO
 *     DATE_ASOF - SAS date for age calculation (Feb 1 of payment year)
 *     FMNAME    - format to crosswalk ICD9 to V03 RXCC
 *     AGEFMT    - format to crosswalk ICD9 to acceptable age range in
 *                 case edits on ICD9 are to be performed 
 *     SEXFMT    - format to crosswalk ICD9 to acceptable sex in case
 *                 edits on ICD9 are to be performed
 *     DF        - factor set by CMS to scale coefficients if required
 *                 (1 = no adjustment made)
 *     AGESEXMAC - external macro name: create age/sex and 
 *                 originally disabled variables
 *     EDITMAC   - external macro name: perform edits to diagnosis
 *     LABELMAC  - external macro name: assign labels to RXHCCs
 *     HIERMAC   - external macro name: set RXHCC=0 according to
 *                 hierarchies
 *     MULTCCMAC - external macro name: assign one ICD9 to multiple 
 *                 RXCCs
 *     SCOREMAC  - external macro name: calculate a score variable
 *
 * External macros:
 *     %AGESEXV4    - create age/sex, originally disabled and nonaged 
 *                    variables
 *     %R03EDIT1    - perform edits to diagnosis
 *     %R02X78M2    - assign one ICD9 to multiple RXCCs
 *     %R02X78L1    - assign labels to RXHCCs
 *     %R02X78H1    - set RXHCC=0 according to hierarchies
 *     %SCOREVAR    - calculate a score variable
 *
 **********************************************************************;

 **********************************************************************;
 * step1: include external macros;
 **********************************************************************;

 %IF "&AGESEXMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&AGESEXMAC) /SOURCE2; %* create demographic variables;
 %END;
 %IF "&EDITMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&EDITMAC)   /SOURCE2; %* perform edits;
 %END;
 %IF "&LABELMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&LABELMAC)  /SOURCE2; %* RXHCC labels;
 %END;
 %IF "&HIERMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&HIERMAC)   /SOURCE2; %* hierarchies;
 %END;
 %IF "&MULTCCMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&MULTCCMAC) /SOURCE2; %* multiple RXCCs;
 %END;
 %IF "&SCOREMAC" ne "" %THEN %DO;
     %INCLUDE IN0(&SCOREMAC)  /SOURCE2; %* calculate score variable;
 %END;

 **********************************************************************;
 * step2: define internal macro variables; 
 **********************************************************************;

 %LET N_RX=180;         %*max # of RXHCCs;
 
 %* 10 NOT AGED continuing enrollee age/sex variables;
 %let NOAGEDAGESEXVARS=%str(
  F0_34  F35_44 F45_54 F55_59 F60_64 
  M0_34  M35_44 M45_54 M55_59 M60_64 
 );

 %* 14 AGED continuing enrollee age/sex variables;
 %let AGEDAGESEXVARS=%str(
  F65_69 F70_74 F75_79 F80_84 F85_89 F90_94 F95_GT
  M65_69 M70_74 M75_79 M80_84 M85_89 M90_94 M95_GT
 );
 
 %* 12 interactions with NonAged for Institutional continuing enrollees;
 %let INTERACTVARS=%str(
  NonAged_RXHCC1   NonAged_RXHCC58   NonAged_RXHCC59 
  NonAged_RXHCC60  NonAged_RXHCC61   NonAged_RXHCC62 
  NonAged_RXHCC63  NonAged_RXHCC65   NonAged_RXHCC75 
  NonAged_RXHCC78  NonAged_RXHCC79   NonAged_RXHCC80 
 );

 %* 8 originally disabled age/sex variables for New Enrollees;
 %let OD_VARS=%str(
  OD_NEF65
  OD_NEF66_69
  OD_NEF70_74
  OD_NEF75_GT
  OD_NEM65
  OD_NEM66_69
  OD_NEM70_74
  OD_NEM75_GT
 );

 %* 8 model variables lists;
 %* (1) Continuing Enrollee Non-Low Income Aged;
 %let MODEL1VARS=%str(
  &AGEDAGESEXVARS
  F65OD
  M65OD
  &RXHCCV3_list78
 );
  
 %* (2) Continuing Enrollee Non-Low Income Non-Aged;
 %let MODEL2VARS=%str(
  &NOAGEDAGESEXVARS
  &RXHCCV3_list78
 );

 %* (3) Continuing Enrollee Low Income Aged;
 %let MODEL3VARS=%str(
  &AGEDAGESEXVARS
  F65OD
  M65OD
  &RXHCCV3_list78
 );
  
 %* (4) Continuing Enrollee Low Income Non-Aged;
 %let MODEL4VARS=%str(
  &NOAGEDAGESEXVARS
  &RXHCCV3_list78
 );

 %* (5) Continuing Enrollee Institutional with Non-Aged Interactions;
 %let MODEL5VARS=%str(
  &AGESEXVARS
  ORIGDS
  &RXHCCV3_list78
  &INTERACTVARS
 );
  
 %* (6) New Enrollee Community Non-Low Income;
 %let MODEL6VARS=%str(
  &NEAGESEXVARS
  &OD_VARS
  ESRD
 );

 %* (7) New Enrollee Community Low Income; 
 %let MODEL7VARS=%str(
  &NEAGESEXVARS
  &OD_VARS
  ESRD
 );

 %* (8) New Enrollee Institutional; 
 %let MODEL8VARS=%str(
  &NEAGESEXVARS
  &OD_VARS
  ESRD
 );
 

 **********************************************************************;
 * step3: merge person and diagnosis files outputting one record
 *        per person with score and RXHCC variables for each input 
 *        person level record
 **********************************************************************;

 DATA &OUTDATA(KEEP=&IDVAR &KEEPVAR );
    ****************************************************;
    * step3.1: declaration section;
    ****************************************************;

    %IF "&LABELMAC" ne "" %THEN %&LABELMAC;   %*RXHCC labels;

    %*length of new variables;
    LENGTH RXCC $4. AGEF 3.
           &OD_VARS
           RXCC1-RXCC&N_RX
           RXHCC1-RXHCC&N_RX
           &INTERACTVARS       3.;

    %*retain cc & age vars;
    RETAIN RXCC1-RXCC&N_RX 0  AGEF
           ;
    %*arrays;
    ARRAY R(&N_RX)  RXCC1-RXCC&N_RX;
    ARRAY RX(&N_RX) RXHCC1-RXHCC&N_RX;
    %*interaction vars;
    ARRAY RV &INTERACTVARS;
    %*array of age/sex cells for new enrollee models;
    ARRAY NEAS(32) &NEAGESEXVARS;

    ****************************************************;
    * step3.2: to bring in regression coefficients;
    ****************************************************;
    IF _N_ = 1 THEN SET INCOEF.RXCOEFF;
   
    ****************************************************;
    * step3.3: merge
    ****************************************************;
    MERGE &INP(IN=IN1)
          &IND(IN=IN2) END=EOF;
    BY &IDVAR;

    RETAIN CNT 0;
    IF IN1 THEN DO;

    ********************************************************;
    * step3.4: for the first record for a person set RXCC to 0
    *          and calculate age
    ********************************************************;

       IF FIRST.&IDVAR THEN DO;
           %*set RXCCs to 0;
           DO I=1 TO &N_RX;
            R(I)=0;
           END;

           %* age;
           AGEF =FLOOR((INTCK(
                'MONTH',DOB,&DATE_ASOF)-(DAY(&DATE_ASOF)<DAY(DOB)))/12);
       END;

    ****************************************************;
    * step3.5 if there are any diagnoses for a person
    *         then do the following:
    *         - create RXCCs using format &FMNAME
    *         - peform ICD9 edits using macro &EDITMAC
    *           if SEDITS=1
    *         - assign additional RXCC using &MULTCCMAC macro
    ****************************************************;
       IF IN1 & IN2 THEN DO;

           RXCC = LEFT(PUT(DIAG,$&FMNAME..));

           IF RXCC NE "-1.0" THEN DO;
              %*perform ICD9 edits;
              %IF "&EDITMAC" ne "" %THEN
                %&EDITMAC(AGE=AGEF, SEX=SEX, ICD9=DIAG);

              IND=INPUT(RXCC,4.);
              IF 1<= IND <= &N_RX THEN DO;
                R(IND)=1;
                %IF "&MULTCCMAC" ne "" %THEN
                %&MULTCCMAC(ICD9=DIAG);  %*multiple RXCCs;
              END;
           END;
       END; %*RXCC creation;

    **************************************************************;
    * step3.6 for the last record for a person do the
    *         following:
    *         - create demographic variables needed (macro &AGESEXMAC)
    *         - create RXHCC using hierarchies (macro &HIERMAC)
    *         - create interaction variables
    *         - set RXHCCs and interaction variables to zero if there
    *           are no diagnoses for a person
    *         - create scores for 5 continuing enrollee models
    *         - create scores for 3 new enrollee models
    **************************************************************;
       IF LAST.&IDVAR THEN DO;

          *****************************;
          * demographic vars           ;
          *****************************;
          %*create age/sex cells and originally disabled variables;
          %IF "&AGESEXMAC" ne "" %THEN
          %&AGESEXMAC(AGEF=AGEF, SEX=SEX, OREC=OREC); 
          %* Originally disabled males/females in aged
          continuing enrollee models;
          F65OD = ORIGDS*(SEX='2'); 
          M65OD = ORIGDS*(SEX='1');
          %* Originally disabled males in new enrollee models;
          OD_NEM65       =(ORIGDS & NEM65 & SEX='1');
          OD_NEM66_69    =(ORIGDS &
                           sum(NEM66,NEM67,NEM68,NEM69) & SEX='1');
          OD_NEM70_74    =(ORIGDS & 70 <= AGEF  <75 & SEX='1');
          OD_NEM75_GT    =(ORIGDS & AGEF >74 & SEX='1');
          %* Originally disabled females in new Enrollee models;
          OD_NEF65      =(ORIGDS & NEF65 & SEX='2');
          OD_NEF66_69   =(ORIGDS &
                          sum(NEF66,NEF67,NEF68,NEF69) & SEX='2');
          OD_NEF70_74   =(ORIGDS & 70 <= AGEF  <75 & SEX='2');
          OD_NEF75_GT   =(ORIGDS & AGEF >74 & SEX='2');


          IF IN1 & IN2 THEN DO;
              **********************;
              * hierarchies;
              **********************;
              %IF "&HIERMAC" ne "" %THEN %&HIERMAC;
              *****************************;
              * other interaction variables;
              *****************************;
   
          %*interactions with NonAged ;
              NonAged_RXHCC1    = NonAged*RXHCC1;
              NonAged_RXHCC58   = NonAged*RXHCC58;
              NonAged_RXHCC59   = NonAged*RXHCC59;
              NonAged_RXHCC60   = NonAged*RXHCC60;
              NonAged_RXHCC61   = NonAged*RXHCC61;
              NonAged_RXHCC62   = NonAged*RXHCC62;
              NonAged_RXHCC63   = NonAged*RXHCC63;
              NonAged_RXHCC65   = NonAged*RXHCC65;
              NonAged_RXHCC75   = NonAged*RXHCC75;
              NonAged_RXHCC78   = NonAged*RXHCC78;
              NonAged_RXHCC79   = NonAged*RXHCC79;
              NonAged_RXHCC80   = NonAged*RXHCC80;
              
          END; %*there are some diagnoses for a person;
          ELSE DO;
              DO I=1 TO &N_RX;
                 RX(I)=0;
              END;
              DO OVER RV;
                 RV=0;
              END;
          END;

          %*score calculation;

          /******************************/
          /* continuing enrollee models */
          /******************************/;
          %IF "&SCOREMAC" ne "" %THEN %DO;
          %* (1) Continuing Enrollee Non-Low Income Aged;
          %&SCOREMAC(PVAR=SCORE_CE_NonLowInc_Aged, 
                     RLIST=&MODEL1VARS, 
                     CPREF=Rx_CE_NoLowAged_);

          %* (2) Continuing Enrollee Non-Low Income Non-Aged;
          %&SCOREMAC(PVAR=SCORE_CE_NonLowInc_NonAged, 
                     RLIST=&MODEL2VARS, 
                     CPREF=Rx_CE_NoLowNoAged_);

          %* (3) Continuing Enrollee Low Income Aged;
          %&SCOREMAC(PVAR=SCORE_CE_LowInc_Aged, 
                     RLIST=&MODEL3VARS, 
                     CPREF=Rx_CE_LowAged_);

          %* (4) Continuing Enrollee Low Income Non-Aged;
          %&SCOREMAC(PVAR=SCORE_CE_LowInc_NonAged, 
                     RLIST=&MODEL4VARS, 
                     CPREF=Rx_CE_LowNoAged_);

          %* (5) Continuing Enrollee Institutional with 
                 Non-Aged Interactions;
          %&SCOREMAC(PVAR=SCORE_CE_Institutional, 
                     RLIST=&MODEL5VARS, 
                     CPREF=Rx_CE_LTI_);

          /***************************/
          /*   new enrollees models  */
          /***************************/;

          %* (6) New Enrollee Community Non-Low Income;
          %&SCOREMAC(PVAR=SCORE_NE_NonLowInc_Community, 
                     RLIST=&MODEL6VARS, 
                     CPREF=Rx_NE_NoLow_);

          %* (7) New Enrollee Community Low Income; 
          %&SCOREMAC(PVAR=SCORE_NE_LowInc_Community, 
                     RLIST=&MODEL7VARS, 
                     CPREF=Rx_NE_Low_);

          %* (8) New Enrollee Institutional; 
          %&SCOREMAC(PVAR=SCORE_NE_Institutional, 
                     RLIST=&MODEL8VARS, 
                     CPREF=Rx_NE_LTI_);
          %END;


          /****************************/
          /*   normalize the scores   */
          /***************************/;
          
          SCORE_CE_NonLowInc_Aged     =SCORE_CE_NonLowInc_Aged*&DF;     
          SCORE_CE_NonLowInc_NonAged  =SCORE_CE_NonLowInc_NonAged*&DF;   
          SCORE_CE_LowInc_Aged        =SCORE_CE_LowInc_Aged*&DF;       
          SCORE_CE_LowInc_NonAged     =SCORE_CE_LowInc_NonAged*&DF;     
          SCORE_CE_Institutional      =SCORE_CE_Institutional*&DF;     
          SCORE_NE_NonLowInc_Community=SCORE_NE_NonLowInc_Community*&DF;
          SCORE_NE_LowInc_Community   =SCORE_NE_LowInc_Community*&DF;  
          SCORE_NE_Institutional      =SCORE_NE_Institutional*&DF;     

          OUTPUT &OUTDATA;
       END; %*last record for a person;
     END; %*there is a person record;
 RUN;


 **********************************************************************;
 * step4: data checks and proc contents
 **********************************************************************;
 PROC PRINT U DATA=&OUTDATA(OBS=46);
     TITLE '*** file outputted by the software ***';
 RUN ;
 PROC CONTENTS DATA=&OUTDATA;
 RUN;

 %MEND R0312I1M;