/*-------------------------------------------------------------------------------------*\
|  PROGRAM NAME:                                                                        |
|     scdm_formats.sas                                                                  |
|                                                                                       | 
|---------------------------------------------------------------------------------------|
|  PURPOSE:                                                                             |
|     The purpose of the program is to store file formats of variables.                 |
|                                                                                       |
|---------------------------------------------------------------------------------------|
|  PROGRAM INPUT:                                                                       |
|     see 00.0_scdm_data_qa_review_master_file.sas                                      |
|                                                                                       |
|  PROGRAM OUTPUT:                                                                      |
|     see Workplan PDF                                                                  |
|---------------------------------------------------------------------------------------|
|  CONTACT:                                                                             |
|     Sentinel Coordinating Center                                                      |
|     info@sentinelsystem.org                                                           |
\*-------------------------------------------------------------------------------------*/

*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-;
*  PLEASE DO NOT EDIT BELOW WITHOUT CONTACTING THE SENTINEL OPERATIONS CENTER           ;
*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-;
%macro create_l1_formats;
  proc sql noprint;
    create table temp as
    select monotonic ( ) as row, max(varlength) as length, * from infolder.lkp_all_l1 (where=(validvaluetype="list_values"))
    where lowcase(variable) ne "ms_result_c"
    ;
  quit;
  %let rowct=&sqlobs.;

  %do i=1 %to &rowct.;
    proc sql noprint;
      select countw(validvalue,'|'), length into :varct trimmed, :length trimmed
      from temp
      where row=&i.
      ;
    quit;

    data temp_&i. (keep=fmtname start); 
      length fmtname $25 start $&length.;      
      set temp (where=(row=&i.));
      start= ' '; 
      fmtname=lowcase(compress('$'||tabid||variable)); 
      output;
      ct+1;
      ct=1;
      do while (ct le &varct.);
        start=scan(validvalue,ct,'|'); 
        fmtname=lowcase(compress('$'||tabid||variable)); 
        output;
        ct+1;
      end;
    run;
  %end;

  data formats;
    set temp_:;
    label='*';
  run;

  proc datasets lib=work;
    delete temp:;
  quit;

  proc format library=dplocal cntlin=formats;
  run; 

%mend;
%create_l1_formats;

proc format library=dplocal;
  value agecat_years
  .       = "00. Missing"
  low-<0  = "00. Negative"
  0-<2    = "01. 0-1 yrs"
  2-<5    = "02. 2-4 yrs"
  5-<10   = "03. 5-9 yrs"
  10-<15  = "04. 10-14 yrs"
  15-<20  = "05. 15-19 yrs"
  20-<25  = "06. 20-24 yrs"
  25-<30  = "07. 25-29 yrs"
  30-<35  = "08. 30-34 yrs"
  35-<40  = "09. 35-39 yrs"
  40-<45  = "10. 40-44 yrs"
  45-<50  = "11. 45-49 yrs"
  50-<55  = "12. 50-54 yrs"
  55-<60  = "13. 55-59 yrs"
  60-<65  = "14. 60-64 yrs"
  65-<70  = "15. 65-69 yrs"
  70-<75  = "16. 70-74 yrs"
  75-<80  = "17. 75-79 yrs"
  80-high = "18. 80+ yrs"
  ;

  value agecat_days
  .         = "00. Missing"
  low-<0    = "01. < 0 days"
  0-30      = "02. 0-30 days"
  31-60     = "03. 31-60 days"
  61-120    = "04. 61-120 days"
  121-180   = "05. 121-180 days"
  181-270  =  "06. 181-270 days"
  271-365   = "07. 271-365 days" 
  366-high  = "08. >= 366 days"
  ;
run;

* SAS VarLength capacity format;
Data _varlenf (drop = bytes capacity);
  length fmtname $8 type label $1 lstart end 8.;
  set infolder.lkp_all_saslength end=eof;
  retain fmtname "varlenf" type "n";
  label = put(bytes,1.);
  end = input(capacity,comma22.);
  lstart = lag(end);
  format lstart end comma22.;
  output;
  if eof then do;
    label = "U";
    hlo = 'O';
    output;
  end;
run; 

Data varlenf (drop = lstart);
  set _varlenf;
  if _n_ = 1 then start = 1;
  else start = lstart + 1;
  run; 

  %macro varlbounds(label,bound);
  /* create a lower bound formatted value based on label (varlength) */
    Data varlenf&label. (drop =_: hlo);
      length fmtname $8 type $1 label start end 8.;
      set varlenf (where=(hlo ne 'O') rename=(label=_label end=_end start=_start));
      fmtname = "&bound.varlenf";
      type = "n";
      label = &label.;
      start = input(_label,8.);
      end = start;
    run;
  %mend;
  %varlbounds(_start,l);
  %varlbounds(_end,u);


proc format library = dplocal cntlin = varlenf; run;
proc format library = dplocal cntlin = varlenf_start; run;
proc format library = dplocal cntlin = varlenf_end; run;

/* ndigfmt is used to compare a SAS length value to a number of allowed digits */
/* Example: a variable with SAS length of 6 would need a formatl value of 12
   in order to avoid possible truncation of display values */ 
Proc format  library=dplocal ; 
  value ndigfmt
    3 = 4
    4 = 7
    5 = 9
    6 = 12
    7 = 14
    8 = 16
  ;
run;

* lab table formats: LOINC;
%macro lab_formats(ds, fmtname); 
  data _lkp_&ds. (drop = loinc);
    length label $20;
    set infolder.lkp_lab_&ds.(keep = loinc MS_Test_Name) end=last;
    retain fmtname "&fmtname." type "c" ;
    start = loinc;
    label = MS_Test_Name;
    output;
    if last then do;
      start = '';
      hlo = 'O';
      label = "0";
      output;
    end;
  run;

  proc format library = dplocal cntlin = _lkp_&ds.; run;
  
  /* format for ms_test_name to result_type, where ms_test_name has one result type */
  proc sql;
    create table lab03fmt (drop = _:) as
      select strip(ms_test_name) as start length=20
           , strip(result_type) as label length=2
           , "lab03fmt" as fmtname
           , "c" as type
           , count(*) as _count
      from infolder.lkp_lab_test (where = (upcase(ms_test_name) ne "UNMAPPED")) 
      group by ms_test_name
      having calculated _count eq 1
      ;
  quit;

  data lab03fmt;
    set lab03fmt end=last;
    output;
    if last then do;
      hlo = 'O';
      label = "NA";
      output;
    end;
  run;

  proc format library = dplocal cntlin = lab03fmt; run;


%mend;
%lab_formats(loinc,LAB07fmt);

* prescribing table formats: rxroute, rxdoseunit, rxdoseform;
%macro pre_formats(ds, fmtname); 
  data _lkp_&ds. (drop = value);
    length label $8;
    set infolder.lkp_pre_&ds.(keep = value) end=last;
    retain fmtname "&fmtname." type "c" ;
    start = value;
    label = "1";
    output;
    if last then do;
      start = '';
      hlo = 'O';
      label = "0";
      output;
    end;
  run;

  proc format library = dplocal cntlin = _lkp_&ds.; run;

%mend;
%pre_formats(rxroute,PRE11fmt);
%pre_formats(rxdoseunit,PRE13fmt);
%pre_formats(rxdoseform,PRE14fmt);

* provider table formats: specialty and specialty_codeType;
%macro pvd_formats(fvar1, fvar2, fmtname, ftype); 
  data _lkp_&fvar1. (keep = fmtname start label hlo);
    length label $8;
    set infolder.lkp_pvd_specialty end=last;
    retain fmtname "$&fmtname." type "ftype." ;
    start = &fvar1.;
    label = put(&fvar2.,1.);
    output;
    if last then do;
      start = '';
      hlo = 'O';
      label = "0";
      output;
    end;
  run;

  proc sort data = _lkp_&fvar1. nodupkey; by start; run;
  proc format library = dplocal cntlin = _lkp_&fvar1.; run;

%mend;
%pvd_formats(specialty,1, PVD02fmt, c);
%pvd_formats(specialty, specialty_codeType, PVD03fmt, c); 

proc datasets nolist lib=work;
  delete _varlenf varlenf _lkp_:;
quit; run;

*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-;
*  End scdm_formats.sas                                                                 ;
*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-;