--- title: "Manufacturing Control" id: 51913 type: "computer_media" slug: "manufacturing-control" url: "http://localhost/computer_media/manufacturing-control/" markdown_url: "http://localhost/computer_media/manufacturing-control.md" published_at: "2023-08-16T01:42:21+00:00" modified_at: "2026-04-04T20:17:54+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-onrh.png" excerpt: "A full manufacturing cost and bill-of-materials system that stores 150 part records, rolls up labor, material, and overhead costs, and supports both BOM explosion and implosion." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Business" slug: "business" taxonomy: "genre" url: "http://localhost/type/business/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/ManufacturingControl (1982)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" images: - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-onrh.png" - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260403-onpe.png" related_products: - id: 13173 title: "Manufacturing Control" type: "product" url: "http://localhost/product/manufacturing-control/" media_type_tags: "Business" --- # Manufacturing Control Manufacturing Control is a bill-of-materials and shop-floor cost management system that stores up to 150 records in a 150×49 character string array. Each record packs part number, department, operation, labor cost, material cost, overhead cost, where-used linkage, quantity per assembly, scrap factor, hours per thousand, and part type (Detail or Assembly) into fixed-width substrings of a single row in R$. The program provides a nine-option menu covering record add, delete, file listing, total cost computation, per-part cost computation, bill-of-materials explosion (finding all components of a parent), and implosion (finding all parents of a component). Numeric fields are stored and retrieved as strings using STR$ and VAL, and the scrap factor is applied during cost rollups with the formula QX=(SC*(Q*NP))+(Q*NP). *** ## Program Analysis ### Program Structure The program is organized as a dispatch loop: lines 20–180 initialize global variables, display a splash screen, and then repeatedly call the menu subroutine at line 1000, branching to one of nine functional subroutines based on the value of `C`. The main loop at line 999 (`GOTO 90`) re-enters the menu after each operation. Line 180 handles option 9 as a `STOP`. | Line Range | Function | | --- | --- | | 20–180 | Initialization, splash screen, dispatch loop | | 1000–1122 | Menu display and input | | 1500–1999 | Add record (calls 1520, 2000, 3000) | | 2000–2040 | Pad P$, D$, O$ to fixed widths | | 2500–2999 | Delete record (blank first byte) | | 3000–3499 | Write record into R$ array | | 3500–3999 | List file (all non-blank records) | | 4000–4010 | Assembly stub: zero M, fall into cost input at 1610 | | 4500–4799 | Compute total costs across all records | | 5500–5999 | Compute costs for a specific part number | | 6000–6020 | Pause/continue subroutine (also supports ‘Q’ to return to menu) | | 6500–6699 | BOM explosion (find components of a parent) | | 7500–7799 | BOM implosion (find parents of a component) | | 8500–8600 | Save data to tape, restart | ### Data Storage Layout All data is held in `R$(150,49)`, a two-dimensional string array of 150 rows, each 49 characters wide. Fields are packed into fixed-width subcolumns using substring slicing. Numeric values are stored as strings via `STR$` and decoded with `VAL` on retrieval. A record is considered deleted when its first byte is set to a space (`R$(N,1 TO 1)=" "`). | Columns | Width | Field | | --- | --- | --- | | 1–5 | 5 | Part number (P$) | | 6–9 | 4 | Department (D$) | | 10–13 | 4 | Operation (O$) | | 14–19 | 6 | Labor cost/hour (L) | | 20–25 | 6 | Material cost/1000 (M) | | 26–31 | 6 | Overhead cost/hour (H) | | 32–36 | 5 | Where-used parent part (W$) | | 37–38 | 2 | Quantity per assembly (NP) | | 39–43 | 5 | Scrap factor (SC) | | 44–48 | 5 | Hours per 1000 (HP) | | 49 | 1 | Type: D=Detail, A=Assembly (E$) | ### Key BASIC Idioms - Fixed-width string padding is applied in subroutine 2000: short inputs are extended with trailing spaces using concatenation, e.g. `LET P$=P$+" "`, ensuring substring slicing always works correctly. - The line `3040 LET R$(N,14 TO 19)=STR$ L` illustrates the pattern of embedding numeric values in string records; all cost and quantity fields are stored this way. - Inverse-video text (e.g. `"%M%E%N%U%"`) is used for headings, labels, and status messages throughout, giving a highlighted appearance on screen. - The `SLOW`/`FAST` mode switches are placed around computation-heavy loops to maximize performance during file scans and revert to display-quality mode for output. - The pause subroutine at line 6000 doubles as a menu-exit shortcut: entering “Q” triggers `GOTO 90`, returning to the main dispatch loop without unwinding the call stack normally. ### Cost Computation The scrap-adjusted quantity formula used in both total-cost (line 4528) and part-cost (line 5607) routines is: `QX = (SC * (Q * NP)) + (Q * NP)` This computes the gross quantity needed including scrap loss. Labor and overhead costs are then multiplied by hours per 1000 (`HP`) since the rates are expressed per hour. All costs are normalized to a base of 1000 parts, and the part-cost routine accepts an arbitrary quantity `Q` which is divided by 1000 at line 5555 before use. ### BOM Explosion and Implosion Explosion (option 6, subroutine 6500) searches all records where the where-used field (`R$(N,32 TO 36)`) matches the entered parent part number, listing all immediate children. Implosion (option 7, subroutine 7500) does the reverse: it searches for records whose part number field (`R$(N,1 TO 5)`) matches the entered part, and displays which parent assembly it belongs to from its where-used field. Neither routine performs recursive multi-level traversal; they are single-level lookups only. ### Notable Techniques and Anomalies - The `LC` counter (line counter) at lines 3522–3524, 6590–6592, and 7620–7622 tracks printed records and calls the pause subroutine after every 3 records to prevent screen scroll overflow. However, `LC` is not reset inside the listing loops themselves — it is only reset in the pause subroutine at line 6015. This means if the user does not press “Q” mid-listing, paging works correctly, but if the subroutine is called at the end of a listing with `LC` not equal to 3, the extra `GOSUB 6000` at the end of each listing routine still provides a final pause. - The Assembly add path (option 1 with E$=”A”) skips the material cost input at line 1635 (`IF E$="A" THEN GOTO 1670`), leaving `M=0` as set at line 4004. This is intentional: assemblies typically have no direct material cost. - The delete routine at line 2550 only blanks the first byte of a record (`R$(N,1 TO 1)=" "`), leaving the rest of the data in memory. This is a deliberate soft-delete: the file search routines treat any record with a blank first byte as an empty slot. - Line 1120 branches to 1090 on invalid menu input — an efficient re-prompt that redisplays from the “8=SAVE DATA” line rather than the full menu, saving screen redraws. - The `SAVE S$` at line 8580 saves the entire program including the populated `R$` array, providing a simple but effective data persistence mechanism without any separate data file handling. - The `STR$` conversion at lines 3040–3090 does not guarantee fixed-width output — a short numeric result from `STR$` will be left-aligned in its field with no padding. This can cause misalignment when `VAL` reads back a substring that contains part of an adjacent field’s data, though in practice the fixed-column slicing keeps fields isolated as long as numbers don’t exceed their allotted widths. ## Source Code ``` 20 DIM R$(150,49) 22 LET XJ=150 25 LET TL=0 27 LET TM=0 28 LET TH=0 30 LET LC=0 40 SLOW 50 PRINT AT 10,10;"TS1000" 60 PRINT AT 11,7;"MANUFACTURING" 70 PRINT AT 12,7;"CONTROL SYSTEM" 80 GOSUB 6000 90 GOSUB 1000 100 IF C=1 THEN GOSUB 1500 110 IF C=2 THEN GOSUB 2500 120 IF C=3 THEN GOSUB 3500 130 IF C=4 THEN GOSUB 4500 140 IF C=5 THEN GOSUB 5500 150 IF C=6 THEN GOSUB 6500 160 IF C=7 THEN GOSUB 7500 170 IF C=8 THEN GOSUB 8500 180 IF C=9 THEN STOP 999 GOTO 90 1000 REM MENU 1010 CLS 1020 PRINT AT 2,0;"%M%E%N%U% %S%E%L%E%C%T%I%O%N% %P%A%N%E%L" 1030 PRINT AT 4,4;"1=ADD PART/DEPT/OPER" 1040 PRINT AT 6,4;"2=DELETE PART/DEPT/OPER" 1050 PRINT AT 8,4;"3=LIST FILE" 1060 PRINT AT 10,4;"4=COMPUTE TOTAL COSTS" 1070 PRINT AT 12,4;"5=COMPUTE PART COST" 1080 PRINT AT 14,4;"6=EXPLODE PART" 1085 PRINT AT 16,4;"7=IMPLODE PART" 1090 PRINT AT 18,4;"8=SAVE DATA" 1095 PRINT AT 20,4;"9=QUIT" 1100 PRINT "%E%N%T%E%R% %O%P%T%I%O%N% %C%O%D%E" 1110 INPUT C 1115 PRINT AT 21,20;C 1120 IF C<1 OR C>9 THEN GOTO 1090 1122 RETURN 1500 REM ADD 1510 CLS 1515 GOSUB 1520 1517 GOTO 1744 1520 PRINT "ENTER PART NO. 5 DIGITS" 1530 INPUT P$ 1540 PRINT P$ 1550 PRINT "ENTER DEPT 4 DIGITS" 1560 INPUT D$ 1570 PRINT D$ 1580 PRINT "ENTER OPERATION 4 DIGITS" 1590 INPUT O$ 1600 PRINT O$ 1602 GOSUB 2000 1605 RETURN 1610 PRINT "I/P LABOR COST/HOUR--6 DIGITS" 1620 INPUT L 1630 PRINT L 1635 IF E$="A" THEN GOTO 1670 1640 PRINT "I/P MATERIAL COST/1000--6 DIGITS" 1650 INPUT M 1660 PRINT M 1670 PRINT "I/P OVERHEAD COST/HOUR--6 DIGITS" 1682 INPUT H 1684 PRINT H 1686 PRINT "I/P SCRAP FACTOR--3 DEC. DIGITS" 1687 INPUT SC 1688 PRINT SC 1690 PRINT "I/P HOURS/1000 - 5 DIGITS" 1692 INPUT HP 1694 PRINT HP 1700 PRINT "ENTER WHERE USED 5 DIGITS" 1710 INPUT W$ 1720 PRINT W$ 1722 LET W=LEN W$ 1725 IF W<5 THEN LET W$=W$+" " 1730 PRINT "ENTER NO. PER ASSY" 1740 INPUT NP 1742 PRINT NP 1743 GOTO 1752 1744 PRINT "ENTER D = DETAIL OR A = ASSY" 1746 INPUT E$ 1748 PRINT E$ 1749 IF E$="D" THEN GOTO 1610 1750 GOTO 4000 1752 FAST 1753 CLS 1760 FOR N=1 TO XJ 1765 IF P$(1 TO 5)=R$(N,1 TO 5) AND D$(1 TO 4)=R$(N,6 TO 9) AND O$(1 TO 4)=R$(N,10 TO 13) THEN GOTO 1800 1770 NEXT N 1790 PRINT "%R%E%C%O%R%D% %A%D%D%E%D" 1792 GOSUB 3000 1796 GOTO 1998 1800 SLOW 1810 PRINT "%R%E%C%O%R%D ALREADY EXISTS" 1820 PRINT 1830 PRINT "YOU MADE AN ERROR" 1840 PRINT 1842 PRINT "PRESS %E%N%T%E%R" 1850 INPUT Y$ 1998 SLOW 1999 RETURN 2000 REM 2002 LET P=LEN P$ 2010 IF P<5 THEN LET P$=P$+" " 2012 LET D=LEN D$ 2020 IF D<4 THEN LET D$=D$+" " 2025 LET O=LEN O$ 2030 IF O<4 THEN LET O$=O$+" " 2040 RETURN 2500 REM DEL 2505 CLS 2510 GOSUB 1520 2515 FAST 2520 FOR N=1 TO XJ 2530 IF P$(1 TO 5)=R$(N,1 TO 5) AND D$(1 TO 4)=R$(N,6 TO 9) AND O$(1 TO 4)=R$(N,10 TO 13) THEN GOTO 2550 2540 NEXT N 2550 CLS 2555 LET R$(N,1 TO 1)=" " 2560 PRINT "RECORD DELETED" 2565 SLOW 2570 GOSUB 6000 2580 GOTO 2999 2999 RETURN 3000 REM 3002 FOR N=1 TO XJ 3004 IF R$(N,1 TO 1)=" " THEN GOTO 3010 3006 NEXT N 3008 PRINT "SORRY-FILE FULL" 3009 GOTO 3100 3010 LET R$(N,1 TO 5)=P$ 3020 LET R$(N,6 TO 9)=D$ 3030 LET R$(N,10 TO 13)=O$ 3040 LET R$(N,14 TO 19)=STR$ L 3050 LET R$(N,20 TO 25)=STR$ M 3052 LET R$(N,26 TO 31)=STR$ H 3060 LET R$(N,32 TO 36)=W$ 3070 LET R$(N,37 TO 38)=STR$ NP 3080 LET R$(N,39 TO 43)=STR$ SC 3090 LET R$(N,44 TO 48)=STR$ HP 3092 LET R$(N,49 TO 49)=E$ 3100 GOSUB 6000 3499 RETURN 3500 REM CHANGE 3504 FAST 3505 CLS 3506 FOR N=1 TO XJ 3508 IF R$(N,1 TO 1)=" " THEN GOTO 3600 3509 PRINT "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 3510 PRINT "%P%A%R%T ";R$(N,1 TO 5);" %D%E%P%T ";R$(N,6 TO 9) 3512 PRINT "%O%P%E%R ";R$(N,10 TO 13);" %L%A%B%O%R ";R$(N,14 TO 19) 3514 PRINT "%M%A%T%L ";R$(N,20 TO 25);" %O%V%H%D ";R$(N,26 TO 31) 3515 PRINT "%U%S%E%D ";R$(N,32 TO 36);" %Q%T%Y%/%P%E%R ";R$(N,37 TO 38) 3517 PRINT "%S%C%R%A%P ";R$(N,39 TO 43);" %H%O%U%R%S ";R$(N,44 TO 48) 3519 PRINT "%T%Y%P%E ";R$(N,49 TO 49) 3522 LET LC=LC+1 3524 IF LC=3 THEN GOSUB 6000 3600 NEXT N 3610 SLOW 3700 GOSUB 6000 3999 RETURN 4000 REM 4004 LET M=0 4010 GOTO 1610 4500 REM 4501 LET TT=0 4502 LET TL=0 4503 LET TM=0 4504 LET TH=0 4505 FAST 4507 LET Q=1 4510 FOR N=1 TO XJ 4520 IF R$(N,1 TO 1)=" " THEN GOTO 4700 4525 LET SC=VAL R$(N,39 TO 43) 4527 LET NP=VAL R$(N,37 TO 38) 4528 LET QX=(SC*(Q*NP)+(Q*NP)) 4530 LET TL=TL+(QX*(VAL R$(N,14 TO 19)*VAL R$(N,44 TO 48))) 4540 LET TM=TM+(QX*VAL R$(N,20 TO 25)) 4550 LET TH=TH+(QX*(VAL R$(N,26 TO 31)*VAL R$(N,44 TO 48))) 4560 LET TT=TT+(QX*VAL R$(N,44 TO 48)) 4700 NEXT N 4710 CLS 4712 SLOW 4720 PRINT 4730 PRINT "%T%O%T%A%L% %L%A%B%O%R = ";TL 4740 PRINT "%T%O%T%A%L% %M%A%T%E%R%I%A%L = ";TM 4744 PRINT "%T%O%T%A%L% %O%V%E%R%H%E%A%D = ";TH 4746 PRINT "%T%O%T%A%L% %H%O%U%R%S = ";TT 4748 PRINT 4749 PRINT "ALL ABOVE BASED ON 1000 PARTS" 4750 GOSUB 6000 4799 RETURN 5500 REM 5502 LET TL=0 5504 LET TM=0 5505 LET TT=0 5506 LET TH=0 5510 CLS 5520 PRINT "ENTER QTY TO BE MADE" 5530 INPUT Q 5540 PRINT Q 5550 PRINT 5555 LET Q=Q/1000 5560 PRINT "ENTER PART NO." 5570 INPUT P$ 5580 PRINT P$ 5581 FAST 5582 GOSUB 2000 5585 FOR N=1 TO XJ 5600 IF P$(1 TO 5)<>R$(N,1 TO 5) AND P$(1 TO 5)<>R$(N,32 TO 36) THEN GOTO 5700 5605 LET SC=VAL R$(N,39 TO 43) 5606 LET NP=VAL R$(N,37 TO 38) 5607 LET QX=(SC*Q*NP)+Q*NP 5610 LET TL=TL+(QX*(VAL R$(N,14 TO 19)*VAL R$(N,44 TO 48))) 5620 LET TM=TM+(QX*VAL R$(N,20 TO 25)) 5630 LET TH=TH+(QX*(VAL R$(N,26 TO 31)*VAL R$(N,44 TO 48))) 5632 LET TT=TT+(QX*VAL R$(N,44 TO 48)) 5700 NEXT N 5710 SLOW 5740 PRINT "%T%O%T%A%L% %E%X%T%.% %L%A%B%O%R =";TL 5750 PRINT "%T%O%T%A%L% %E%X%T%.% %M%A%T%L =";TM 5760 PRINT "%T%O%T%A%L% %E%X%T%.% %O%V%H%D =";TH 5762 PRINT "%T%O%T%A%L% %E%X%T%.% %H%O%U%R%S =";TT 5780 GOSUB 6000 5999 RETURN 6000 PRINT AT 21,0;"%P%R%E%S%S% %E%N%T%E%R% OR ENTER A Q" 6010 INPUT Y$ 6011 IF Y$="Q" THEN SLOW 6012 IF Y$="Q" THEN GOTO 90 6015 LET LC=0 6017 CLS 6020 RETURN 6500 REM 6510 CLS 6520 PRINT "ENTER PART TO BE EXPLODED" 6530 INPUT W$ 6535 PRINT W$ 6536 LET W=LEN W$ 6538 IF W<5 THEN LET W$=W$+" " 6540 FAST 6550 FOR N=1 TO XJ 6560 IF R$(N,1 TO 1)=" " THEN GOTO 6600 6570 IF W$(1 TO 5)<>R$(N,32 TO 36) THEN GOTO 6600 6575 PRINT "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 6580 PRINT R$(N,32 TO 36);"---";"%P%A%R%T ";R$(N,1 TO 5) 6582 PRINT "%D%E%P%T ";R$(N,6 TO 9) 6584 PRINT "%O%P%E%R ";R$(N,10 TO 13) 6586 PRINT "%Q%T%Y%/%P%E%R ";R$(N,37 TO 38) 6588 PRINT "%T%Y%P%E ";R$(N,49 TO 49) 6590 LET LC=LC+1 6592 IF LC=3 THEN GOSUB 6000 6600 NEXT N 6605 SLOW 6610 GOSUB 6000 6699 RETURN 7500 REM 7510 CLS 7520 PRINT "ENTER PART TO BE IMPLODED" 7530 INPUT P$ 7540 PRINT P$ 7550 GOSUB 2000 7555 FAST 7560 FOR N=1 TO XJ 7570 IF P$(1 TO 5)<>R$(N,1 TO 5) THEN GOTO 7700 7580 PRINT "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" 7590 PRINT R$(N,1 TO 5);"---";" %U%S%E%D ";R$(N,32 TO 36) 7600 PRINT "%D%E%P%T ";R$(N,6 TO 9) 7610 PRINT "%O%P%E%R ";R$(N,10 TO 13) 7612 PRINT "%Q%T%Y%/%P%E%R ";R$(N,37 TO 38) 7614 PRINT "%T%Y%P%E ";R$(N,49 TO 49) 7620 LET LC=LC+1 7622 IF LC=3 THEN GOSUB 6000 7700 NEXT N 7705 SLOW 7710 GOSUB 6000 7799 RETURN 8500 REM 8510 CLS 8520 PRINT "ENTER NAME OF FILE" 8530 INPUT S$ 8540 PRINT S$ 8550 PRINT "SET RECORDER FOR SAVE MODE" 8560 PRINT "PRESS ENTER WHEN READY" 8570 INPUT Y$ 8580 SAVE S$ 8590 CLS 8600 GOTO 40 ```