T/S-1500 Biorhythm Monitor

Date: 198x
Type: Program
Platform(s): TS 1500

Works out your physical, sensitivity and cognitive biorhythm cycles from your birth date and a chosen start date, and plots them for one to seven days. Name, birth date, start date and number of days go into a framed on-screen form, and an ERRORS box flags values that are too big. The chart shows the day of the week, the date and the month and year for each column, with an inverse P, S or C marking each cycle’s position and an inverse * where cycles overlap. The heading shows the number of days you have been alive. When the chart is finished you can copy it to the printer, run the program again or quit.

The opening screen reads "WELCOME TO THE T/S-1500 BIORHYTHM MONITOR". The tape holds a normal copy and an autorun copy of the same program.

Program Analysis

Program Structure

  • Lines 10–272: set up arrays for day names, month names and month lengths, then call the input form at 4100.
  • Lines 4100–5270: the input form, with range checks and right-aligned display of each number in the form. A ready screen warns that the display will go blank for about 30 seconds while the program works in FAST mode.
  • Lines 290–680: date arithmetic. The century is removed from both years, the day of the year is built from month lengths with a leap year correction, and the total days lived S and an absolute day number D3 are worked out.
  • Lines 741–1950: plotting. For each day the program prints the weekday (from D3 modulo 7), the date and the month and year, works out the three cycle values, and draws the markers in a column. The date then moves on by one day, rolling over months and years.
  • Lines 4000–4095: the key and the C/R/Q option loop. COPY sends the screen to the printer.

Notable Techniques

  • Cycle positions come from INT (20*SIN ((S/P-INT (S/P))*6.28318)+40.5) with P=18+5*I, giving the standard 23-, 28- and 33-day periods. Values from 20 to 60 are mapped to screen rows with two straight-line formulas, one for each half of the curve.
  • Overlap is checked two ways: matching cycle values are drawn as *, and so is any marker that falls on the same row as the one just drawn.
  • A 64×64 string array C$ is set up, but only its diagonal C$(X,X) is used, as a one-dimensional map of which cycle sits at each value. That uses 4K of memory to hold 64 characters.
  • Markers are printed with CHR$ codes for inverse letters (181 = P, 184 = S, 168 = C, 151 = *).
  • Line 774 changes a one-day request into two so that the column spacing (Q-1)*25/(D9-1) never divides by zero.

Potential Issues

  • Line 1940 uses Y(1) (the birth year) instead of Y(2) when resetting February’s length after a year rollover, so a chart that crosses into a new year can get leap years wrong.
  • Leap years are taken as every fourth year, with no century rule.
  • Day entry is checked against a February length of 28, so a 29 February birth date is rejected.
  • The ready screen asks you to press ENTER, but any key carries on.
  • Lines 6000–6010 cannot be reached.

Image Gallery

Source Code

   1 REM 
  10 REM "BIORHYTHM"
  20 FAST
  25 CLS
  30 DIM A(12)
  40 DIM B$(12,3)
  50 DIM C$(64,64)
  55 LET Z$=""
  60 DIM A$(12,3)
  70 LET Z=0
  71 DIM X(3)
  72 LET Q$=" "
  74 LET ST=99
 212 LET A$(1)="MON"
 213 LET A$(2)="TUE"
 214 LET A$(3)="WED"
 215 LET A$(4)="THU"
 216 LET A$(5)="FRI"
 217 LET A$(6)="SAT"
 218 LET A$(7)="SUN"
 220 LET A(1)=31
 222 LET A(2)=28
 224 LET A(3)=31
 225 LET A(4)=30
 227 LET A(5)=31
 228 LET A(6)=30
 229 LET A(7)=31
 230 LET A(8)=31
 232 LET A(9)=30
 234 LET A(10)=31
 236 LET A(11)=30
 238 LET A(12)=31
 250 LET B$(1)="JAN"
 252 LET B$(2)="FEB"
 254 LET B$(3)="MAR"
 256 LET B$(4)="APR"
 258 LET B$(5)="MAY"
 260 LET B$(6)="JUN"
 262 LET B$(7)="JUL"
 264 LET B$(8)="AUG"
 266 LET B$(9)="SEP"
 268 LET B$(10)="OCT"
 270 LET B$(11)="NOV"
 272 LET B$(12)="DEC"
 280 GOSUB 4100
 290 FAST
 302 FOR N=10 TO 100
 304 IF N*100>Y(1) THEN GOTO 308
 306 NEXT N
 308 LET Y(1)=Y(1)-((N-1)*100)
 310 IF M(1)=1 THEN GOTO 411
 320 LET A(2)=29-SGN (Y(1)/4-INT (Y(1)/4))
 330 FOR I=1 TO M(1)-1
 340 LET D(1)=D(1)+A(I)
 350 NEXT I
 411 LET D0=D(2)
 415 LET Y(2)=Y(2)-((N-1)*100)
 422 LET A(2)=29-SGN (Y(2)/4-INT (Y(2)/4))
 430 IF M(2)=1 THEN GOTO 500
 440 FOR I=1 TO M(2)-1
 450 LET D(2)=D(2)+A(I)
 460 NEXT I
 500 LET S=0
 505 FOR I=Y(1)+1 TO Y(2)-1
 510 IF I/4=INT (I/4) THEN LET S=S+1
 515 NEXT I
 520 IF Y(1)/4=INT (Y(1)/4) THEN LET S=S+1
 530 IF D(1)>59 THEN GOTO 600
 550 LET S=S+((Y(2)-Y(1)-1)*365)
 560 LET S=S+(365-D(1))
 570 LET S=S+D(2)
 580 GOTO 650
 600 IF Y(1)/4=INT (Y(1)/4) THEN LET S=S-1
 610 GOTO 550
 650 LET D3=Y(2)*365+D(2)
 660 FOR I=1 TO Y(2)-1
 670 IF I/4=INT (I/4) THEN LET D3=D3+1
 680 NEXT I
 720 LET D(2)=D0
 740 GOSUB 2000
 741 FOR N=1 TO 63
 742 PLOT N,17
 743 NEXT N
 745 FOR N=0 TO 31
 746 PRINT AT 2,N;CHR$ 8
 747 NEXT N
 750 FOR Q=1 TO D9
 752 FOR I=1 TO 63
 753 LET C$(I,I)="-"
 754 NEXT I
 760 LET GG=D3-1
 770 LET E=INT (7*(GG/7-INT (GG/7))+0.5)+1
 774 IF D9=1 THEN LET D9=2
 775 LET R=(Q-1)*25/(D9-1)
 780 PRINT AT 3,R;A$(E)
 790 PRINT AT 4,R;D(2)
 800 LET Z7=0
 810 IF Z<1 THEN GOTO 900
 815 IF D(2)<>1 THEN GOTO 940
 900 PRINT AT 5,R;B$(M(2))
 905 LET Z7=1
 907 IF Y(2)>=100 THEN LET Y(2)=100*(Y(2)/100-INT (Y(2)/100))
 910 PRINT AT 6,R;Y(2)
 915 LET Z=Z+1
 940 IF A$(E)="SUN" THEN GOTO 1000
 950 REM 
 960 REM 
 965 REM 
 970 GOTO 1060
1000 REM 
1005 REM 
1010 REM 
1060 FOR I=1 TO 3
1070 LET P=18+(5*I)
1080 LET X(I)=INT (20*SIN ((S/P-INT (S/P))*6.28318)+40.5)
1090 NEXT I
1100 REM 
1114 PRINT AT 13,31;"0"
1115 PRINT AT 13,0;"0"
1116 LET C$(X(1),X(1))="P"
1120 IF X(1)<>X(2) THEN GOTO 1400
1130 IF X(1)<>X(3) THEN GOTO 1400
1140 IF X(2)<>X(3) THEN GOTO 1400
1150 LET C$(X(1),X(1))="*"
1160 GOTO 1800
1400 IF X(1)<>X(2) THEN GOTO 1500
1410 LET C$(X(3),X(3))="C"
1420 GOTO 1510
1500 IF X(2)<>X(3) THEN GOTO 1600
1510 LET C$(X(2),X(2))="*"
1520 GOTO 1800
1600 LET C$(X(2),X(2))="S"
1610 IF X(1)=X(3) THEN GOTO 1150
1620 LET C$(X(3),X(3))="C"
1800 REM 
1810 FOR X=15 TO 63
1811 IF C$(X,X)="-" THEN GOTO 1830
1812 IF C$(X,X)="P" THEN LET J$=CHR$ 181
1813 IF C$(X,X)="S" THEN LET J$=CHR$ 184
1814 IF C$(X,X)="C" THEN LET J$=CHR$ 168
1815 IF X=40 THEN LET T=13
1816 IF X>40 THEN LET T=INT (X*-.2173913)+21
1817 IF X<40 THEN LET T=INT (X*-.2)+21
1818 IF C$(X,X)="*" THEN LET J$=CHR$ 151
1819 IF T=ST THEN LET J$=CHR$ 151
1820 PRINT AT T,R;J$
1821 PRINT AT 21,31;"█";AT 21,31;" "
1822 LET ST=T
1830 NEXT X
1835 LET ST=99
1840 REM 
1850 LET D3=D3+1
1860 LET S=S+1
1865 LET D(2)=D(2)+1
1870 IF D(2)<A(M(2))+1 THEN GOTO 4000
1880 LET D(2)=1
1890 LET M(2)=M(2)+1
1900 IF M(2)<13 THEN GOTO 4000
1910 LET M(2)=1
1920 LET Y(2)=Y(2)+1
1940 LET A(2)=29-SGN (Y(1)/4-INT (Y(1)/4))
1950 GOTO 4000
1999 STOP
2000 REM 
2005 CLS
2010 PRINT "BIORHYTHM CHART FOR ";Z$
2020 PRINT "YOU HAVE LIVED FOR ";S;" DAYS"
3000 RETURN
4000 NEXT Q
4005 FOR N=0 TO 31
4006 PRINT AT 19,N;CHR$ 8
4007 NEXT N
4010 PRINT AT 20,0;"[P]=PHYSICAL,[S]=SENSITIVITY"
4020 PRINT AT 21,0;"[C]=COGNITIVE,[*]=OVERLAP"
4030 PRINT AT 19,4;"C-COPY, R-RERUN, Q-QUIT"
4035 SLOW
4040 IF INKEY$ ="C" THEN GOTO 4090
4050 IF INKEY$ ="Q" THEN GOTO 5300
4060 IF INKEY$ ="R" THEN RUN 
4070 GOTO 4040
4090 PRINT AT 19,4;"▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒"
4092 COPY
4095 GOTO 4030
4100 PRINT AT 1,9;"WELCOME TO THE"
4110 PRINT AT 2,3;"T/S-1500 BIORHYTHM MONITOR"
4120 PRINT AT 3,3;"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
4130 FOR N=6 TO 17
4140 PRINT AT N,1;"▐▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▌"
4150 NEXT N
4160 PRINT AT 5,1;"▗▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▖"
4170 PRINT AT 18,1;"▝▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▘"
4180 PRINT AT 7,3;"[B][I][O][R][H][Y][T][H][M]█[F][O][R][:]"
4190 PRINT AT 13,4;"[B][I][R][T][H][D][A][T][E]▒▒▒▒▒▒[P][L][O][T][-][D][A][T][E]"
4195 PRINT AT 20,0;"                                "
4200 PRINT AT 15,3;"[M][O]▒[D][A][Y]▒[Y][E][A][R]▒▒▒▒[M][O]▒[D][A][Y]▒[Y][E][A][R]"
4210 PRINT AT 16,3;"00▒00▒▒0000▒▒▒▒00▒00▒▒0000"
4230 PRINT AT 9,4;"[N][O][.]█[O][F]█[D][A][Y][S]"
4240 PRINT AT 10,6;"[T][O]█[P][L][O][T]"
4250 PRINT AT 11,9;0
4260 PRINT AT 9,20;"[E][R][R][O][R][S]"
4270 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]"
4275 SLOW
4277 IF Z$<>"" THEN GOTO 4352
4280 PRINT AT 21,0;"WHAT IS YOUR NAME?"
4290 INPUT Z$
4300 IF LEN (Z$)<12 THEN GOTO 4350
4310 PRINT AT 10,20;"TOO LONG"
4320 PAUSE 150
4330 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒▒"
4340 GOTO 4280
4350 PRINT AT 7,18;Z$
4352 DIM M(2)
4354 DIM D(2)
4356 DIM Y(2)
4360 FOR N=1 TO 2
4370 IF N=2 THEN GOTO 4400
4380 PRINT AT 20,0;"*DATE OF BIRTH*                "
4390 GOTO 4410
4400 PRINT AT 20,0;"*DATE TO START GRAPH*      "
4410 PRINT AT 21,0;"   ENTER MONTH                 "
4420 INPUT M(N)
4430 IF M(N)>12 THEN GOTO 4480
4450 IF M(N)<10 THEN PRINT AT 16,4+((N-1)*15);M(N)
4460 IF M(N)>9 THEN PRINT AT 16,3+((N-1)*15);M(N)
4470 GOTO 4500
4480 PRINT AT 10,20;"TOO BIG"
4490 PAUSE 150
4492 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒"
4495 GOTO 4420
4500 PRINT AT 21,0;"   ENTER DAY                   "
4505 INPUT D(N)
4510 IF D(N)>A(M(N)) THEN GOTO 4550
4520 IF D(N)<10 THEN PRINT AT 16,7+((N-1)*15);D(N)
4530 IF D(N)>9 THEN PRINT AT 16,6+((N-1)*15);D(N)
4540 GOTO 5000
4550 PRINT AT 10,20;"TOO BIG"
4560 PAUSE 150
4570 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒]▒"
4580 GOTO 4505
5000 PRINT AT 21,0;"   ENTER YEAR (ALL 4 DIGITS)"
5010 INPUT Y(N)
5012 IF Y(N)<=9999 THEN GOTO 5020
5014 PRINT AT 10,20;"TOO HIGH"
5016 PAUSE 150
5017 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒][▒]▒"
5018 GOTO 5010
5020 IF Y(N)>=10 THEN GOTO 5023
5021 PRINT AT 16,13+((N-1)*15);Y(N)
5022 GOTO 5030
5023 IF Y(N)>=100 THEN GOTO 5026
5024 PRINT AT 16,12+((N-1)*15);Y(N)
5025 GOTO 5030
5026 IF Y(N)>=1000 THEN GOTO 5029
5027 PRINT AT 16,11+((N-1)*15);Y(N)
5028 GOTO 5030
5029 PRINT AT 16,10+((N-1)*15);Y(N)
5030 NEXT N
5040 PRINT AT 20,0;"                               "
5050 PRINT AT 21,0;"ENTER NO. OF DAYS TO PLOT (1-7)"
5060 INPUT D9
5070 IF D9<=7 THEN GOTO 5130
5080 PRINT AT 10,20;"TOO MANY"
5100 PAUSE 150
5110 PRINT AT 10,20;"[▒][▒][▒][▒][▒][▒][▒][▒]"
5120 GOTO 5060
5130 PRINT AT 11,9;D9
5140 PRINT AT 21,0;"                               ";AT 20,0;"IS ALL THE DATA CORRECT? (Y/N)"
5150 IF INKEY$ ="N" THEN GOTO 4190
5160 IF INKEY$ ="Y" THEN GOTO 5180
5170 GOTO 5150
5180 FAST
5182 CLS
5185 PRINT AT 1,3;"THE COMPUTER IS NOW READY"
5190 PRINT AT 2,3;"TO MAKE A BIORHYTHM CHART"
5195 PRINT AT 3,3;"FOR ";Z$;"."
5200 PRINT AT 5,3;"WHEN YOU ARE READY, ALL YOU"
5205 PRINT AT 6,3;"NEED TO DO IS PRESS [E][N][T][E][R]"
5210 PRINT AT 8,3;"THE COMPUTER WILL THEN GO"
5215 PRINT AT 9,3;"BLANK FOR APPROXIMATELY 30"
5220 PRINT AT 10,3;"SECONDS.                     " 
5225 PRINT AT 12,3;"WHEN THE GRAPH C0MES UP, YOU"
5230 PRINT AT 13,3;"WILL HAVE 3 OPTIONS AVAILABLE"
5235 PRINT AT 15,5;"[C]-COPY GRAPH ONTO PRINTER"
5240 PRINT AT 17,5;"[R]-RUN THE PROGRAM AGAIN"
5245 PRINT AT 19,5;"[Q]-STOP THE PROGRAM"
5250 PRINT AT 21,3;"PRESS [E][N][T][E][R] WHEN READY"
5255 SLOW
5260 IF INKEY$ ="" THEN GOTO 5260
5270 RETURN
5299 STOP
5300 CLS
5310 PRINT AT 3,5;"THANK-YOU FOR PLAYING"
5315 PRINT AT 5,0;"AND I HOPE YOU ENJOYED YOURSELF."
5320 STOP
6000 PRINT AT 21,31;"▐";AT 21,31;"▌"
6010 GOTO 1830
9995 SAVE "BI[O]"
9996 RUN

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.