Job Jar

Products: Job Jar
Date: 198x
Type: Cassette
Platform(s): TS 1000
Tags: Home

This program implements a “Job Jar” task management system, allowing the user to initialise a job list, add job descriptions with time estimates, mark jobs as done (removing them from the list with an array shift), pick a random job matching available time, list all jobs, and save the program to tape. Job entries are stored in a dimensioned string array B$ with 28 characters per record: 24 characters for the description and 3 characters (positions 26–28) for a numeric time estimate. The PICK function (line 4000) implements a rudimentary time-matching and randomised selection algorithm that decrements the requested time by one each pass until a matching job is found, using RND to introduce non-determinism. The save routine at line 9550 renders a pixel-accurate bitmap of the text “JOB” by reading character ROM data via PEEK from address 7680, printing inverse or normal space characters to reconstruct each glyph on screen.


Program Analysis

Program Structure

The program is organised as a menu-driven application with a central dispatcher at line 490–600 and several functional modules at higher line numbers. Shared subroutines at lines 10–70 handle common prompts (Y/N confirmation, “More?”, “Press C”, and printer copy). The main modules are:

  1. Lines 490–600: Main menu and dispatcher
  2. Lines 1000–1050: Initialise — dimension the job array
  3. Lines 2000–2170: Add a job entry
  4. Lines 3000–3160: Mark a job done and remove it
  5. Lines 4000–4260: Pick a random job by available time
  6. Lines 5000–5050: List all jobs
  7. Lines 9550–9680: Save program and display logo splash screen

Data Storage

Jobs are stored in a two-dimensional string array B$ dimensioned at line 1030 as DIM B$(N1,28). Each record uses a fixed 28-character layout:

PositionsContent
1–24Job description (free text)
25Unused / padding
26–28Time estimate (numeric string, right-padded with spaces)

A scratch buffer X$ of 28 characters is dimensioned at line 2020 for each add operation, then copied wholesale into B$(N) at line 2140.

Input Validation

Both the ADD and PICK routines validate their numeric inputs by iterating character-by-character over the time-estimate field. The condition at lines 2070 and 4050, IF X$(K)<"A" AND X$(K)>".", attempts to accept only digits (which lie between "." and "A" in the ZX81 character set). Spaces are accepted as padding after the first character (lines 2064, 4044). This validation is applied in a FOR loop but uses GOTO to skip the first character check, which skips validation for position 26 entirely — a minor anomaly that could allow a non-digit leading character.

Job Deletion by Array Compaction

When a job is marked done (line 3000 module), the array is compacted by shifting all subsequent entries down one position (lines 3070–3090), then decrementing the job counter N at line 3100. This is a classic in-place list deletion without pointer arithmetic, achieved purely in BASIC.

Random Job Picker Algorithm

The PICK routine (lines 4085–4260) is a two-phase search. It scans all N jobs for one whose time estimate string matches X$(1 TO 3). If none is found and the search has not already been expanded (X=1 at line 4130), it decrements the requested time by 1 and retries — effectively widening the search downward. Once a matching job is found (line 4110), it is selected only with probability 1/3 using IF INT(RND*3+1)<>1 at line 4200, providing randomisation across multiple matches. The variable X is set to 1 at line 4090 on the assumption that the loop sets it, but there is a bug: X is only reset to 0 at line 4090 at the top of each retry pass, never explicitly set to 1 in the no-match path; line 4130 checks X=1 which will never be true, so the decrement loop runs indefinitely if no match is ever found.

Additionally, line 4160 contains IF T=0 THEN LET T1=T1+1, which increments T1 when the counter reaches zero, but this value is never used thereafter — this appears to be dead or vestigial code.

Character ROM Logo Renderer

The save splash screen (lines 9565–9645) renders the letters “JOB” pixel-by-pixel by reading the character ROM. For each letter in A$="JOB", it retrieves the ASCII code with CODE A$(NN) and reads 8 bytes from address 7680 + C*8 + H via PEEK. Each byte is decomposed bit-by-bit by repeatedly testing against a bitmask V (starting at 128 and halved each iteration). Set bits are printed as inverse space characters ("% ") and clear bits as a block graphic ("\@@" = two @ characters rendered as a light block). The three letters are spaced 7 columns apart starting at column 5, and rendered starting at row 3, producing a large pixelated title.

Subroutine Conventions and GOSUB Usage

Three shared subroutines are invoked repeatedly:

  • GOSUB 10 — “CHANGE Y OR N?” prompt; sets flag F=1 for Y, F=0 for N
  • GOSUB 30 — “MORE Y OR N?” prompt; falls through to line 14 of subroutine 10
  • GOSUB 40 — “PRESS C TO CONTINUE” prompt
  • GOSUB 60 — “COPY Y OR N?” prompt with optional COPY to printer

Subroutine 30 at line 34 jumps directly into the body of subroutine 10 at line 14, sharing its Y/N polling loop and RETURN — a deliberate code-reuse technique via fall-through.

Key BASIC Idioms

  • Inverse-video text in messages (e.g. "%B%A%D% %E%S%T%I%M%A%T%E") uses the ZX81 inverse character escape to highlight error notices.
  • RAND 0 at line 490 seeds the random number generator to a fixed value, ensuring reproducible picks each session start.
  • SLOW / FAST mode switching is used around the display-intensive logo renderer and the main menu to balance display quality versus computation speed.
  • The copy subroutine at line 62 uses a double-poll pattern (IF INKEY$<>"" THEN GOTO 62 followed by IF INKEY$="" THEN GOTO 64) to wait for a key release then a new keypress, debouncing the input.

Content

Appears On

Related Products

Let your computer keep tabs on your odd jobs. Input the time you have available and the program will select...

Related Articles

Related Content

Image Gallery

Source Code

  10 LET F=0
  12 PRINT AT 21,0;"CHANGE Y OR N"
  14 IF INKEY$="Y" THEN GOTO 20
  16 IF INKEY$="N" THEN GOTO 22
  18 GOTO 14
  20 LET F=1
  22 PRINT AT 21,0;"                                "
  24 RETURN 
  30 LET F=0
  32 PRINT AT 21,0;"MORE Y OR N"
  34 GOTO 14
  40 PRINT AT 21,0;"PRESS C TO CONTINUE"
  42 IF INKEY$="C" THEN GOTO 22
  44 GOTO 42
  60 PRINT AT 21,0;"COPY Y OR N?"
  62 IF INKEY$<>"" THEN GOTO 62
  64 IF INKEY$="" THEN GOTO 64
  66 IF INKEY$="N" THEN RETURN 
  68 IF INKEY$="Y" THEN COPY 
  70 GOTO 62
 490 RAND 0
 500 CLS 
 510 SLOW 
 520 PRINT "I=INITIAL, A=ADD, D=DONE"
 530 PRINT "P=PICK, L=LIST, S=SAVE"
 540 IF INKEY$="I" THEN GOTO 1000
 550 IF INKEY$="A" THEN GOTO 2000
 560 IF INKEY$="D" THEN GOTO 3000
 570 IF INKEY$="P" THEN GOTO 4000
 580 IF INKEY$="L" THEN GOTO 5000
 590 IF INKEY$="S" THEN GOTO 9550
 600 GOTO 540
 1000 CLS 
 1010 PRINT "INPUT NUMBER OF JOBS"
 1020 INPUT N1
 1030 DIM B$(N1,28)
 1040 LET N=0
 1050 GOTO 500
 2000 CLS 
 2002 IF N<>N1 THEN GOTO 2008
 2004 PRINT "% NO MORE ROOM IN FILE% "
 2006 PAUSE 100
 2007 GOTO 500
 2008 CLS 
 2009 PRINT "   NUMBER OF JOBS=";N
 2010 PRINT AT 1,0;"   INPUT DESCRIPTION FOR JOB ";N+1
 2020 DIM X$(28)
 2030 INPUT X$(1 TO 24)
 2035 PRINT AT 2,0;"*";X$(1 TO 24)
 2040 PRINT AT 3,0;"   HOURS FOR JOB ";N+1;"=";
 2050 INPUT X$(26 TO 28)
 2060 FOR K=26 TO 28
 2062 IF K=26 THEN GOTO 2070
 2064 IF X$(K)=" " THEN GOTO 2100
 2070 IF X$(K)<"A" AND X$(K)>"." THEN GOTO 2100
 2080 PRINT "%B%A%D% %E%S%T%I%M%A%T%E"
 2090 GOTO 2040
 2100 NEXT K
 2105 PRINT X$(26 TO 28);"         "
 2110 GOSUB 10
 2120 IF F=1 THEN GOTO 2008
 2130 LET N=N+1
 2140 LET B$(N)=X$
 2150 GOSUB 30
 2160 IF F=1 THEN GOTO 2000
 2170 GOTO 500
 3000 CLS 
 3010 PRINT "I HAVE COMPLETED NO. ";
 3020 INPUT I
 3030 IF I>N THEN GOTO 3000
 3035 PRINT I
 3040 PRINT B$(I)
 3050 GOSUB 10
 3060 IF F=1 THEN GOTO 3010
 3070 FOR J=I TO N-1
 3080 LET B$(J)=B$(J+1)
 3090 NEXT J
 3100 LET N=N-1
 3110 GOSUB 30
 3120 IF F=0 THEN GOTO 500
 3130 IF N<>0 THEN GOTO 3000
 3140 PRINT "%N%O% %M%O%R%E% %J%O%B%S"
 3150 PAUSE 100
 3160 GOTO 500
 4000 CLS 
 4005 DIM X$(3)
 4010 IF N=0 THEN GOTO 3140
 4020 PRINT "INPUT AVAILABLE TIME"
 4030 INPUT X$(1 TO 3)
 4040 FOR K=1 TO 3
 4042 IF K=1 THEN GOTO 4050
 4044 IF X$(K)=" " THEN GOTO 4080
 4050 IF X$(K)<"A" AND X$(K)>"." THEN GOTO 4080
 4060 PRINT "%B%A%D% %I%N%P%U%T"
 4065 PAUSE 100
 4070 GOTO 4000
 4080 NEXT K
 4085 FAST 
 4090 LET X=0
 4100 FOR K=1 TO N
 4110 IF B$(K,26 TO 28)=X$(1 TO 3) THEN GOTO 4200
 4120 NEXT K
 4130 IF X=1 THEN GOTO 4090
 4140 LET T=VAL X$(1 TO 3)
 4145 LET T1=T
 4150 LET T=T-1
 4160 IF T=0 THEN LET T1=T1+1
 4170 LET X$(1 TO 3)=STR$ T
 4180 GOTO 4090
 4200 IF INT (RND*3+1)<>1 THEN GOTO 4090
 4210 CLS 
 4215 SLOW 
 4220 PRINT "%J%O%B% %I%S:"
 4230 PRINT B$(K)
 4240 PRINT 
 4250 GOSUB 40
 4260 GOTO 500
 5000 CLS 
 5010 FOR K=1 TO N
 5020 PRINT K;TAB 4;B$(K)
 5030 NEXT K
 5040 GOSUB 60
 5050 GOTO 500
 9550 CLS 
 9551 SAVE "JO%B"
 9555 LET A$="JOB"
 9560 FAST 
 9565 LET NN=0
 9570 FOR L=5 TO 19 STEP 7
 9575 LET NN=NN+1
 9580 LET C=CODE A$(NN)
 9585 FOR H=0 TO 7
 9590 LET P=PEEK (7680+C*8+H)
 9595 LET V=128
 9600 FOR G=0 TO 7
 9605 IF P<V THEN GOTO 9625
 9610 PRINT AT H+3,G+L;"% "
 9615 LET P=P-V
 9620 GOTO 9630
 9625 PRINT AT H+3,G+L;"@@"
 9630 LET V=V/2
 9635 NEXT G
 9640 NEXT H
 9645 NEXT L
 9650 PRINT "     JOB JAR COPYRIGHT UAS"
 9655 PRINT "BOX 612 HADDONFIELD, N.J. 08033"
 9660 PAUSE 200
 9670 CLS 
 9680 GOTO 490

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

People

No people associated with this content.

Scroll to Top