' Line Graph — draws ASCII line graphs from data arrays
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL data(100) AS LONG
    LOCAL n AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL k AS LONG
    LOCAL graphHeight AS LONG
    LOCAL graphWidth AS LONG
    LOCAL minVal AS LONG
    LOCAL maxVal AS LONG
    LOCAL valRange AS LONG
    LOCAL charPos AS LONG
    LOCAL prevCharPos AS LONG
    LOCAL lineStr AS STRING
    LOCAL elemStr AS STRING
    LOCAL y AS LONG
    LOCAL scaledVal AS LONG
    LOCAL rowStr AS STRING
    n = 40
    graphHeight = 20
    graphWidth = n
    PRINT "============================================"
    PRINT "          ASCII LINE GRAPH"
    PRINT "============================================"
    PRINT ""
    FOR i = 0 TO n - 1
        data(i) = ((i * 13 + 7) MOD 30) + 10 + (SIN(i * 0.3) * 10)
    NEXT i
    minVal = data(0)
    maxVal = data(0)
    FOR i = 1 TO n - 1
        IF data(i) < minVal THEN
            minVal = data(i)
        END IF
        IF data(i) > maxVal THEN
            maxVal = data(i)
        END IF
    NEXT i
    valRange = maxVal - minVal
    IF valRange < 1 THEN
        valRange = 1
    END IF
    PRINT "Data range: " + STR$(minVal) + " to " + STR$(maxVal)
    PRINT ""
    FOR y = graphHeight - 1 TO 0 STEP -1
        lineStr = ""
        FOR i = 0 TO n - 1
            scaledVal = (data(i) - minVal) * (graphHeight - 1) / valRange
            IF scaledVal = y THEN
                lineStr = lineStr + "*"
            ELSE
                IF scaledVal > y THEN
                    lineStr = lineStr + "|"
                ELSE
                    lineStr = lineStr + " "
                END IF
            END IF
            IF scaledVal = y AND i > 0 THEN
                prevCharPos = (data(i - 1) - minVal) * (graphHeight - 1) / valRange
                IF prevCharPos = y THEN
                    lineStr = MID$(lineStr, 1, LEN(lineStr) - 1) + "*"
                END IF
            END IF
        NEXT i
        PRINT "|" + lineStr
    NEXT y
    lineStr = ""
    FOR i = 0 TO n - 1
        lineStr = lineStr + "-"
    NEXT i
    PRINT "+" + lineStr
    PRINT ""
    PRINT "============================================"
    PRINT "     SMOOTH LINE GRAPH (interpolated)"
    PRINT "============================================"
    PRINT ""
    n = 20
    graphHeight = 12
    FOR i = 0 TO n - 1
        data(i) = ((i * 7 + 3) MOD 20) + 5
    NEXT i
    minVal = data(0)
    maxVal = data(0)
    FOR i = 1 TO n - 1
        IF data(i) < minVal THEN
            minVal = data(i)
        END IF
        IF data(i) > maxVal THEN
            maxVal = data(i)
        END IF
    NEXT i
    valRange = maxVal - minVal
    IF valRange < 1 THEN
        valRange = 1
    END IF
    PRINT "Smoothed line graph:"
    PRINT ""
    FOR y = graphHeight - 1 TO 0 STEP -1
        lineStr = ""
        FOR i = 0 TO n - 1
            scaledVal = (data(i) - minVal) * (graphHeight - 1) / valRange
            IF scaledVal >= y AND scaledVal <= y + 1 THEN
                lineStr = lineStr + "#"
            ELSE
                IF scaledVal > y THEN
                    lineStr = lineStr + "|"
                ELSE
                    IF scaledVal < y AND i > 0 AND i < n - 1 THEN
                        prevCharPos = (data(i - 1) - minVal) * (graphHeight - 1) / valRange
                        IF prevCharPos > y THEN
                            lineStr = lineStr + "~"
                        ELSE
                            lineStr = lineStr + " "
                        END IF
                    ELSE
                        lineStr = lineStr + " "
                    END IF
                END IF
            END IF
        NEXT i
        PRINT "|" + lineStr
    NEXT y
    lineStr = ""
    FOR i = 0 TO n - 1
        lineStr = lineStr + "-"
    NEXT i
    PRINT "+" + lineStr
    PRINT ""
    PRINT "============================================"
    PRINT "     SCATTER PLOT"
    PRINT "============================================"
    PRINT ""
    LOCAL scatterX(60) AS LONG
    LOCAL scatterY(60) AS LONG
    n = 30
    FOR i = 0 TO n - 1
        scatterX(i) = i * 2
        scatterY(i) = ((i * 11 + 5) MOD 15) + 3
    NEXT i
    graphWidth = 40
    graphHeight = 14
    PRINT "Scatter plot:"
    PRINT ""
    FOR y = graphHeight TO 1 STEP -1
        lineStr = ""
        FOR x = 0 TO graphWidth
            charPos = 0
            FOR i = 0 TO n - 1
                IF scatterX(i) = x AND scatterY(i) = y THEN
                    charPos = 1
                    EXIT FOR
                END IF
            NEXT i
            IF charPos = 1 THEN
                lineStr = lineStr + "O"
            ELSE
                IF y = 1 THEN
                    lineStr = lineStr + "-"
                ELSE
                    IF x = 0 THEN
                        lineStr = lineStr + "|"
                    ELSE
                        lineStr = lineStr + " "
                    END IF
                END IF
            END IF
        NEXT x
        PRINT lineStr
    NEXT y
    PRINT ""
    PRINT "============================================"
    PRINT "     MULTI-LINE OVERLAY"
    PRINT "============================================"
    PRINT ""
    LOCAL dataA(60) AS LONG
    LOCAL dataB(60) AS LONG
    n = 30
    FOR i = 0 TO n - 1
        dataA(i) = ((i * 7 + 3) MOD 20) + 5
        dataB(i) = ((i * 11 + 7) MOD 20) + 3
    NEXT i
    graphHeight = 14
    minVal = dataA(0)
    maxVal = dataA(0)
    FOR i = 1 TO n - 1
        IF dataA(i) < minVal THEN
            minVal = dataA(i)
        END IF
        IF dataA(i) > maxVal THEN
            maxVal = dataA(i)
        END IF
        IF dataB(i) < minVal THEN
            minVal = dataB(i)
        END IF
        IF dataB(i) > maxVal THEN
            maxVal = dataB(i)
        END IF
    NEXT i
    valRange = maxVal - minVal
    IF valRange < 1 THEN
        valRange = 1
    END IF
    PRINT "Two data series (A=*, B=#):"
    PRINT ""
    FOR y = graphHeight - 1 TO 0 STEP -1
        lineStr = ""
        FOR i = 0 TO n - 1
            scaledVal = (dataA(i) - minVal) * (graphHeight - 1) / valRange
            IF scaledVal = y THEN
                lineStr = lineStr + "*"
            ELSE
                scaledVal = (dataB(i) - minVal) * (graphHeight - 1) / valRange
                IF scaledVal = y THEN
                    lineStr = lineStr + "#"
                ELSE
                    scaledVal = (dataA(i) - minVal) * (graphHeight - 1) / valRange
                    IF scaledVal > y THEN
                        IF (dataB(i) - minVal) * (graphHeight - 1) / valRange > y THEN
                            lineStr = lineStr + "X"
                        ELSE
                            lineStr = lineStr + "|"
                        END IF
                    ELSE
                        scaledVal = (dataB(i) - minVal) * (graphHeight - 1) / valRange
                        IF scaledVal > y THEN
                            lineStr = lineStr + ":"
                        ELSE
                            lineStr = lineStr + " "
                        END IF
                    END IF
                END IF
            END IF
        NEXT i
        PRINT "|" + lineStr
    NEXT y
    PRINT ""
    PRINT "Line graph demonstration complete"
    FUNCTION = 0
END FUNCTION
