Biorhythm

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

This program calculates and displays biorhythm charts for three cycles — Physical (23 days), Emotional (28 days), and Intellectual (33 days) — based on a user-supplied date of birth and today’s date. Date validation at line 1000 checks string length, delimiter placement, and digit validity before converting the DD.MM.YY input into a day-count using month-length data encoded in the string `m$` as ASCII offset values (e.g., `CODE m$(m)-20` yields the number of days in month `m`). Leap year correction is applied when the year is divisible by 4 and the accumulated day count has passed February. The chart is plotted using PLOT and SIN with a scaling factor of 20 pixels amplitude, and month boundaries are marked by vertical tick lines driven by the same `m$` encoding used during date parsing.


Program Structure

The program is divided into four logical sections:

  1. Lines 10–90: Setup, color attributes, and input loop for birth date and today’s date.
  2. Lines 100–340: Cycle calculation and chart rendering including sine-wave plotting and month-boundary markers.
  3. Lines 1000–1550: Subroutine that validates a date string and converts it to an absolute day number stored in n.
  4. Line 2000–2010: Error handler that sets flag x=1 and prints a flashing “INVALID DATE” message.

The m$ Encoding Trick

The string m$="303232332323" at line 20 encodes month lengths in a compact form. Each character’s ASCII code minus 20 yields the number of days in that month: '3' = 51−20 = 31, '0' = 48−20 = 28, '2' = 50−20 = 30. This avoids a DATA statement or array, and the same string is reused both in the date-to-day conversion (lines 1090–1530) and in the month-boundary tick-mark loop (lines 300–330).

Date Validation Subroutine (Lines 1000–1550)

The subroutine performs several layered checks before attempting numeric conversion:

  • Exact length of 8 characters (line 1010).
  • Dots at positions 3 and 6 (line 1020).
  • Digit characters at positions 1–2, 4–5, and 7–8 via a loop stepping by 3 (lines 1030–1050).
  • Non-zero day, month, and year, and month ≤ 12 (line 1070).

An anomaly exists at line 1090: it calculates the days in month m into n (including leap-day adjustment for February), but this value is immediately overwritten by LET n=0 at line 1500 without being used. The intent was likely to validate that the day number does not exceed the month length, but that check was never implemented — so invalid days such as 31 in April pass silently.

Day-Count Calculation

Lines 1500–1550 sum month lengths for all months before m, add a leap-year correction if the accumulated count has passed day 59 (end of February), then add the day-of-month and an approximation of prior complete years using INT (365.25*(y-1)). This gives a relative Julian-style day number sufficient for computing the difference between two dates. The two-digit year y means dates in different centuries are not distinguished, though this is typical for the era.

Biorhythm Calculation and Plotting

Line 130 derives cycle periods: b(1)=23, b(2)=28, b(3)=33, matching Physical, Emotional, and Intellectual cycles. Line 140 computes c(j), the phase offset (days into the current cycle). The sine wave is plotted at line 230:

PLOT INK j; k, SIN((k + 2*c(j)) * PI / b(j)) * 20 + ((4-j)*48-28)

The factor 2*c(j) in the argument shifts the curve horizontally so the chart’s left edge represents the current date. Each cycle is drawn in a different INK color (1=blue, 2=red, 3=green) and centered on its own horizontal baseline at vertical positions 20, 68, and 116 pixels respectively.

Month Boundary Markers (Lines 300–330)

A second pass over all 256 x-coordinates draws short vertical tick marks at month boundaries. Variable d accumulates 0.5 per pixel column and is compared against CODE m$(m)-20 (days in month m). When the threshold is exceeded, d resets and m advances. Note that d is also used as the day-of-month variable in the date parsing subroutine (line 1060), so if the chart section is reached, d retains whatever value was left from parsing. This is benign because d is effectively initialized to a small value before the comparison matters, but it is a variable reuse that could cause confusion.

Notable Techniques and Anomalies

  • The typo “Pleasr” (missing ‘e’) in the PRINT statement at line 30 is a cosmetic bug in the original listing.
  • Error handling uses a flag variable x rather than structured error trapping, with GO TO 2000 used as a shared error exit from multiple validation points.
  • The DIM n$(3,12) at line 100 allocates fixed-length strings; “Physical” (8 chars), “Emotional” (9), and “Intellectual” (12) are padded to 12 by the DIM, so labels display correctly without manual padding.
  • Line 1090 computes a value into n that is immediately discarded by line 1500’s LET n=0, representing an incomplete validation or refactoring artifact.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   10 INK 2:BORDER 6:PAPER 6:BRIGHT 1:CLS 
   20 LET m$="303232332323"
   30 PRINT TAB 11;"BIORHYTHM"'''''"Pleasr enter dates in the form:"''' TAB 11;"DD.MM.YY"
   40 INPUT "Enter your date of birth ";d$
   50 GO SUB 1000:IF x THEN GO TO 40
   60 LET b=n:LET b$=d$
   70 INPUT "Enter today's date ";d$
   80 GO SUB 1000:IF x THEN GO TO 70
   90 LET n=n-b:IF n<0 THEN GO SUB 2000:GO TO 70
  100 DIM n$(3,12):LET n$(1)="Physical":LET n$(2)="Emotional":LET n$(3)="Intellectual"
  110 DIM b(3):DIM c(3)
  120 FOR j=1 TO 3
  130  LET b(j)=18+5*j
  140  LET c(j)=n-b(j)* INT (n/b(j))
  150 NEXT j
  200 CLS :PRINT TAB 11;"BIOCHART"''"D.O.B.:";b$;"Today:";d$
  210 INK 7:FOR j=1 TO 3:PLOT 0,j*48-28:DRAW 255,0:PRINT INK j; AT j*6-2,2;n$(j):NEXT j
  220 FOR j=1 TO 3:FOR k=0 TO 255
  230 PLOT INK j;k, SIN ((k+(2*c(j)))* PI/b(j))*20+((4-j)*48-28)
  240 NEXT k:NEXT j
  300 FOR j=0 TO 255
  310 LET d=d+.5
  320 IF d> CODE m$(m)-20 THEN LET d=.5:FOR k=1 TO 3:PLOT j,k*48-30:DRAW 0,5:NEXT k:LET m=m+1:IF m>12 THEN LET m=1
  330 NEXT j
  340 STOP 
 1000 LET x=0:PRINT AT 15,10;"            ":REM 12 spaces
 1010 IF LEN d$ <>8 THEN GO TO 2000
 1020 IF d$(3) <>"." OR d$(6) <>"." THEN GO TO 2000
 1030 FOR j=1 TO 7 STEP 3
 1040 IF d$(j)<"0" OR d$(j)>"9" OR d$(j+1)<"0" OR d$(j+1)>"9" THEN GO TO 2000
 1050 NEXT j
 1060 LET y= VAL d$(7 TO ):LET m= VAL d$(4 TO 5):LET d= VAL d$( TO 2)
 1070 IF y=0 OR d=0 OR m=0 OR m>12 THEN GO TO 2000
 1080 LET l=0:IF y/4= INT y/4 THEN LET l=1
 1090 LET n= CODE m$(m)-20+(m=2 AND l=1)
 1500 LET n=0
 1510 FOR j=1 TO m-1
 1520 LET n=n+ CODE m$(j)-20
 1530 NEXT j
 1540 IF l=1 AND n>59 THEN LET n=n+1
 1550 LET n=n+d+ INT (365.25*(y-1)):RETURN 
 2000 LET x=1
 2010 PRINT INK 2; FLASH 1; AT 15,10;"\{16}\{2}INVALID DATE":RETURN 
 9000 SAVE "BIORHYTHMS" LINE 0

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

People

No people associated with this content.

Scroll to Top