dos_compilers/Microsoft QuickBASIC v45/EXAMPLES/BAR.BAS
2024-07-01 21:19:24 -07:00

220 lines
6.0 KiB
QBasic

' Define type for the titles:
TYPE TitleType
MainTitle AS STRING * 40
XTitle AS STRING * 40
YTitle AS STRING * 18
END TYPE
DECLARE SUB InputTitles (T AS TitleType)
DECLARE FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value!(), N%)
DECLARE FUNCTION InputData% (Label$(), Value!())
' Variable declarations for titles and bar data:
DIM Titles AS TitleType, Label$(1 TO 5), Value(1 TO 5)
CONST FALSE = 0, TRUE = NOT FALSE
DO
InputTitles Titles
N% = InputData%(Label$(), Value())
IF N% <> FALSE THEN
NewGraph$ = DrawGraph$(Titles, Label$(), Value(), N%)
END IF
LOOP WHILE NewGraph$ = "Y"
END
REM $STATIC
'
' ========================== DRAWGRAPH =========================
' Draws a bar graph from the data entered in the INPUTTITLES
' and INPUTDATA procedures.
' ==============================================================
'
FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value(), N%) STATIC
' Set size of graph:
CONST GRAPHTOP = 24, GRAPHBOTTOM = 171
CONST GRAPHLEFT = 48, GRAPHRIGHT = 624
CONST YLENGTH = GRAPHBOTTOM - GRAPHTOP
' Calculate max/min values:
YMax = 0
YMin = 0
FOR I% = 1 TO N%
IF Value(I%) < YMin THEN YMin = Value(I%)
IF Value(I%) > YMax THEN YMax = Value(I%)
NEXT I%
' Calculate width of bars and space between them:
BarWidth = (GRAPHRIGHT - GRAPHLEFT) / N%
BarSpace = .2 * BarWidth
BarWidth = BarWidth - BarSpace
SCREEN 2
CLS
' Draw y axis:
LINE (GRAPHLEFT, GRAPHTOP)-(GRAPHLEFT, GRAPHBOTTOM), 1
' Draw main graph title:
Start% = 44 - (LEN(RTRIM$(T.MainTitle)) / 2)
LOCATE 2, Start%
PRINT RTRIM$(T.MainTitle);
' Annotate Y axis:
Start% = CINT(13 - LEN(RTRIM$(T.YTitle)) / 2)
FOR I% = 1 TO LEN(RTRIM$(T.YTitle))
LOCATE Start% + I% - 1, 1
PRINT MID$(T.YTitle, I%, 1);
NEXT I%
' Calculate scale factor so labels aren't bigger than 4 digits:
IF ABS(YMax) > ABS(YMin) THEN
Power = YMax
ELSE
Power = YMin
END IF
Power = CINT(LOG(ABS(Power) / 100) / LOG(10))
IF Power < 0 THEN Power = 0
' Scale min and max down:
ScaleFactor = 10 ^ Power
YMax = CINT(YMax / ScaleFactor)
YMin = CINT(YMin / ScaleFactor)
' If power isn't zero then put scale factor on chart:
IF Power <> 0 THEN
LOCATE 3, 2
PRINT "x 10^"; LTRIM$(STR$(Power))
END IF
' Put tic mark and number for Max point on Y axis:
LINE (GRAPHLEFT - 3, GRAPHTOP)-STEP(3, 0)
LOCATE 4, 2
PRINT USING "####"; YMax
' Put tic mark and number for Min point on Y axis:
LINE (GRAPHLEFT - 3, GRAPHBOTTOM)-STEP(3, 0)
LOCATE 22, 2
PRINT USING "####"; YMin
' Scale min and max back up for charting calculations:
YMax = YMax * ScaleFactor
YMin = YMin * ScaleFactor
' Annotate X axis:
Start% = 44 - (LEN(RTRIM$(T.XTitle)) / 2)
LOCATE 25, Start%
PRINT RTRIM$(T.XTitle);
' Calculate the pixel range for the Y axis:
YRange = YMax - YMin
' Define a diagonally striped pattern:
Tile$ = CHR$(1) + CHR$(2) + CHR$(4) + CHR$(8) + CHR$(16) + CHR$(32) + CHR$(64) + CHR$(128)
' Draw a zero line if appropriate:
IF YMin < 0 THEN
Bottom = GRAPHBOTTOM - ((-YMin) / YRange * YLENGTH)
LOCATE INT((Bottom - 1) / 8) + 1, 5
PRINT "0";
ELSE
Bottom = GRAPHBOTTOM
END IF
' Draw x axis:
LINE (GRAPHLEFT - 3, Bottom)-(GRAPHRIGHT, Bottom)
' Draw bars and labels:
Start% = GRAPHLEFT + (BarSpace / 2)
FOR I% = 1 TO N%
' Draw a bar label:
BarMid = Start% + (BarWidth / 2)
CharMid = INT((BarMid - 1) / 8) + 1
LOCATE 23, CharMid - INT(LEN(RTRIM$(Label$(I%))) / 2)
PRINT Label$(I%);
' Draw the bar and fill it with the striped pattern:
BarHeight = (Value(I%) / YRange) * YLENGTH
LINE (Start%, Bottom)-STEP(BarWidth, -BarHeight), , B
PAINT (BarMid, Bottom - (BarHeight / 2)), Tile$, 1
Start% = Start% + BarWidth + BarSpace
NEXT I%
LOCATE 1, 1, 1
PRINT "New graph? ";
DrawGraph$ = UCASE$(INPUT$(1))
END FUNCTION
'
' ========================= INPUTDATA ========================
' Gets input for the bar labels and their values
' ============================================================
'
FUNCTION InputData% (Label$(), Value()) STATIC
' Initialize the number of data values:
NumData% = 0
' Print data-entry instructions:
CLS
PRINT "Enter data for up to 5 bars:"
PRINT " * Enter the label and value for each bar."
PRINT " * Values can be negative."
PRINT " * Enter a blank label to stop."
PRINT
PRINT "After viewing the graph, press any key ";
PRINT "to end the program."
' Accept data until blank label or 5 entries:
Done% = FALSE
DO
NumData% = NumData% + 1
PRINT
PRINT "Bar("; LTRIM$(STR$(NumData%)); "):"
INPUT ; " Label? ", Label$(NumData%)
' Only input value if label isn't blank:
IF Label$(NumData%) <> "" THEN
LOCATE , 35
INPUT "Value? ", Value(NumData%)
' If label was blank, decrement data counter and
' set Done flag equal to TRUE:
ELSE
NumData% = NumData% - 1
Done% = TRUE
END IF
LOOP UNTIL (NumData% = 5) OR Done%
' Return the number of data values input:
InputData% = NumData%
END FUNCTION
'
' ======================= INPUTTITLES ========================
' Accepts input for the three different graph titles
' ============================================================
'
SUB InputTitles (T AS TitleType) STATIC
' Set text screen:
SCREEN 0, 0
' Input Titles
DO
CLS
INPUT "Enter main graph title: ", T.MainTitle
INPUT "Enter X-Axis title : ", T.XTitle
INPUT "Enter Y-Axis title : ", T.YTitle
' Check to see if titles are OK:
LOCATE 7, 1
PRINT "OK (Y to continue, N to change)? ";
LOCATE , , 1
OK$ = UCASE$(INPUT$(1))
LOOP UNTIL OK$ = "Y"
END SUB