I attach a Rexx program to calculate and display the biorhythm values
for a given date of birth and current or whatever other date.
 
If 'management' complains that home workers are not putting enough
effort into their working-from-home time, they can run this thing and
send its output to 'management' just to prove that they are in perfect
working condition and that any slow-down in productivity must be due to
external factors which are wholly beyond their control <g>.
 
Cheers, Chris Poncelet (retired sysprog)

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN
/*********************************************************************/
/* Calculate Biorhythm Program                                       */
/*                                                                   */
/* Based on theory that physical, emotional and intellectual cycles  */
/* vary from 1.00 to -1.00 every 23, 28 and 33 days from the date of */
/* birth onwards - where positive scores are "up days" and negative  */
/* scores indicate "down days"                                       */
/*                                                                   */
/* Cycles:                                                           */
/* - Physical     : 23 days                                          */
/* - Emotional    : 28 days                                          */
/* - Intellectual : 33 days                                          */
/*                                                                   */
/* Paramters:                                                        */
/* - DATE1          : date of birth                                  */
/* - DATE2          : current date                                   */
/* - DEBUG          : to debug this thing, if required               */
/*                                                                   */
/*                                                                   */
/* 2020/04/04 Chris Poncelet                                         */
/*********************************************************************/
ARG DATE1 DATE2 DEBUG

IF ABBREV(DEBUG,'D') = 1 THEN ,
  TRACE I

NUMERIC DIGITS 100

/* CHECK THAT START DATE1 IS EARLIER THAN END DATE DATE2 */
IF DATE2 ¬> DATE1 THEN ,
  DO
  SAY 'START DATE 'DATE1' MUST BE EARLIER THAN END DATE 'DATE2'.'
  SAY ' '
  SAY 'PLEASE TRY AGAIN.'
  SAY ' '
  CALL EXIT
  END /* IF */

/* CHECK THAT DATE1 DATA IS VALID AND WHETHER LEAP YEAR ETC. */
Q = DATE1
CALL CHECK_DATE

/* CONVERT DATE1 YEARS, MONTHS, DAYS TO FACTOR */
CALL GET_FACTOR
FACTOR1 = FACTOR

/* CALCULATE DAY OF THE WEEK FOR DATE1 */
DW1 = FACTOR + TRUNC(-FACTOR/7)*7
SELECT
  WHEN DW1 = 0 THEN DW1 = '(SATURDAY)'
  WHEN DW1 = 1 THEN DW1 = '(SUNDAY)'
  WHEN DW1 = 2 THEN DW1 = '(MONDAY)'
  WHEN DW1 = 3 THEN DW1 = '(TUESDAY)'
  WHEN DW1 = 4 THEN DW1 = '(WEDNESDAY)'
  WHEN DW1 = 5 THEN DW1 = '(THURSDAY)'
  WHEN DW1 = 6 THEN DW1 = '(FRIDAY)'
  OTHERWISE NOP
  END /* SELECT */
SAY 'WE HAVE YEAR = 'YEAR', MONTH = 'MONTH', DAY = 'DAY' 'DW1
SAY ' '

/* CHECK THAT DATE2 DATA IS VALID AND WHETHER LEAP YEAR ETC. */
Q = DATE2
CALL CHECK_DATE

/* CONVERT DATE2 YEARS, MONTHS, DAYS TO FACTOR */
CALL GET_FACTOR
FACTOR2 = FACTOR

/* CALCULATE DAY OF THE WEEK FOR DATE2 */
DW2 = FACTOR + TRUNC(-FACTOR/7)*7
SELECT
  WHEN DW2 = 0 THEN DW2 = '(SATURDAY)'
  WHEN DW2 = 1 THEN DW2 = '(SUNDAY)'
  WHEN DW2 = 2 THEN DW2 = '(MONDAY)'
  WHEN DW2 = 3 THEN DW2 = '(TUESDAY)'
  WHEN DW2 = 4 THEN DW2 = '(WEDNESDAY)'
  WHEN DW2 = 5 THEN DW2 = '(THURSDAY)'
  WHEN DW2 = 6 THEN DW2 = '(FRIDAY)'
  OTHERWISE NOP
  END /* SELECT */
SAY 'WE HAVE YEAR = 'YEAR', MONTH = 'MONTH', DAY = 'DAY' 'DW2
SAY ' '


#DAYS = FACTOR2 - FACTOR1
SAY 'ELAPSED NUMBER OF DAYS IS '#DAYS
SAY ' '

/* NOW GET PHYSICAL, EMOTIONAL AND INTELLECTUAL CYCLE SCORES */
Q = #DAYS/23
CALL GET_SINE
P = QS
IF P < 0 THEN ,
  SAY 'PHYSICAL      : 'FORMAT(QS,,2)
ELSE,
  SAY 'PHYSICAL      :  'FORMAT(QS,,2)
SAY ' '

Q = #DAYS/28
CALL GET_SINE
E = QS
IF E < 0 THEN ,
  SAY 'EMOTIONAL     : 'FORMAT(QS,,2)
ELSE ,
  SAY 'EMOTIONAL     :  'FORMAT(QS,,2)
SAY ' '

Q = #DAYS/33
CALL GET_SINE
I = QS
IF I < 0 THEN ,
  SAY 'INTELLECTUAL  : 'FORMAT(QS,,2)
ELSE ,
  SAY 'INTELLECTUAL  :  'FORMAT(QS,,2)
SAY ' '

AV = (P+E+I)/3
IF AV < 0 THEN ,
  SAY 'AVERAGE       : 'FORMAT(AV,,2)
ELSE ,
  SAY 'AVERAGE       :  'FORMAT(AV,,2)
SAY ' '

CALL EXIT


/*********************************************************************/
/* SUBROUTINES                                                       */
/*********************************************************************/


CHECK_DATE:
/* CHECK THAT DATE IS NUMERIC AND IN THE CORRECT FORMAT */
IF DATATYPE(Q,N) ¬= 1 ,
|  DATATYPE(SUBSTR(Q,1,4),W) ¬= 1 ,
|  DATATYPE(SUBSTR(Q,6,4),W) ¬= 1 ,
|  LENGTH(Q) ¬= 9 ,
|  SUBSTR(Q,5,1) ¬= '.' THEN ,
  DO
  SAY '"'Q'"' 'MUST BE NUMERIC IN THE FORM "yyyy.mmdd"'
  SAY ' '
  SAY 'PLEASE TRY AGAIN'
  SAY ' '
  CALL EXIT
  END /* IF */
ELSE ,
  DO
/* CHECK THAT DATE IS WITHIN VALID RANGES */
  YEAR  = TRUNC(Q)
  MONTH = SUBSTR(Q,6,2)
  DAY   = SUBSTR(Q,8,2)

  IF  (YEAR < 1582 | MONTH < 1 | MONTH > 12 | DAY < 1 | DAY > 31) THEN ,
    DO
    IF  (YEAR < 1582 ) THEN ,
      SAY 'YEAR  = 'YEAR' MUST BE AT LEAST 1582 (GREGORIAN CALENDAR)'
    IF  (MONTH < 1 | MONTH > 12) THEN ,
      SAY 'MONTH = 'MONTH' CANNOT BE LESS THAN 01 OR MORE THAN 12'
    IF  (DAY < 1 | DAY > 31) THEN ,
      SAY 'DAY   = 'DAY' CANNOT BE LESS THAN 01 OR MORE THAN 31'
    SAY ' '
    CALL EXIT
    END /* IF */

/* CHECK WHETHER THIS YEAR IS A LEAP YEAR */
  LEAP  = (YEAR -YEAR%4*4 = 0 & YEAR - YEAR%400*400 ¬= 0)

/* CHECK THAT DATE IS VALID FOR FEBRUARY */
  IF MONTH == 02 & DAY > 29 & LEAP THEN ,
    DO
    SAY 'MONTH 'MONTH' IN YEAR 'YEAR' CANNOT HAVE MORE THAN 29 DAYS'
    SAY ' '
    CALL EXIT
    END /* IF */
  IF MONTH == 02 & DAY > 28 & ¬LEAP THEN ,
    DO
    SAY 'MONTH 'MONTH' IN YEAR 'YEAR' CANNOT HAVE MORE THAN 28 DAYS'
    SAY ' '
    CALL EXIT
    END /* IF */

/* CHECK THAT DATE IS VALID FOR ALL OTHER MONTHS OF THE YEAR */
  IF (MONTH == 01  ,
  |   MONTH == 03  ,
  |   MONTH == 05  ,
  |   MONTH == 07  ,
  |   MONTH == 08  ,
  |   MONTH == 10  ,
  |   MONTH == 12) ,
  &  (DAY > 31) THEN ,
    DO
    SAY 'MONTH 'MONTH' CANNOT HAVE MORE THAN 31 DAYS'
    SAY ' '
    CALL EXIT
    END /* IF */
  IF (MONTH == 04  ,
  |   MONTH == 06  ,
  |   MONTH == 09  ,
  |   MONTH == 11) ,
  &  (DAY > 30) THEN ,
    DO
    SAY 'MONTH 'MONTH' CANNOT HAVE MORE THAN 30 DAYS'
    SAY ' '
    CALL EXIT
    END /* IF */

  END /* ELSE */
RETURN

GET_FACTOR:
/* CALCULATE THE FACTOR FOR GIVEN DATE (LOGIC CRIBBED FROM MY TI-58'S ML20 */
  MM = MONTH
  YY = YEAR
  DD = DAY
  FACTOR = YY*365+DD+(MM-1)*31
  SELECT
    WHEN (MONTH == 01 | MONTH == 02) THEN ,
      FACTOR = ,
       FACTOR+TRUNC((YY-1)/4)-TRUNC((TRUNC((YY-1)/100)+1)*3/4)
    OTHERWISE ,
      FACTOR = ,
       FACTOR-TRUNC(0.4*MM+2.3)+TRUNC(YY/4)-TRUNC((TRUNC(YY/100)+1)*3/4)
  END /* SELECT */
  RETURN FACTOR

GET_SINE:
/* CALCULATE THE SINE OF THE ELAPSED NUMBER OF DAYS IN RADIANS */
PI =  3.1415926535897932384626433832795
QR =  Q*PI*2

T  = TRUNC(QR/(PI*2))
QR = QR - T*PI*2

T  =  QR
F  =  1
QS =  T

DO I = 1 TO 52 BY 4
  F  = F*(I+1)*(I+2)
  QS = QS-T**(I+2)/F
  F  = F*(I+3)*(I+4)
  QS = QS+T**(I+4)/F
  END I

RETURN QS

EXIT:
  EXIT 0

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to [email protected] with the message: INFO IBM-MAIN

Reply via email to