220 lines
6.0 KiB
QBasic
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
|