' Pie Chart — draws ASCII pie charts from data proportions
#COMPILE EXE
#DIM ALL

FUNCTION ArcTan(BYVAL x AS DOUBLE) AS DOUBLE
    LOCAL x2 AS DOUBLE
    LOCAL r AS DOUBLE
    IF x < 0 THEN
        FUNCTION = 0 - ArcTan(0 - x)
        EXIT FUNCTION
    END IF
    IF x > 1 THEN
        FUNCTION = 1.5707963267948966 - ArcTan(1.0 / x)
        EXIT FUNCTION
    END IF
    x2 = x * x
    r = x * (0.999866 + x2 * (-0.330299 + x2 * (0.180141 + x2 * (-0.085133 + x2 * 0.020835))))
    FUNCTION = r
END FUNCTION

FUNCTION PBMAIN() AS LONG
    LOCAL data(20) AS LONG
    LOCAL labels(20) AS STRING
    LOCAL n AS LONG
    LOCAL i AS LONG
    LOCAL j AS LONG
    LOCAL k AS LONG
    LOCAL total AS LONG
    LOCAL angles(20) AS LONG
    LOCAL startAngle AS LONG
    LOCAL endAngle AS LONG
    LOCAL midAngle AS LONG
    LOCAL radius AS LONG
    LOCAL x AS LONG
    LOCAL y AS LONG
    LOCAL cx AS LONG
    LOCAL cy AS LONG
    LOCAL grid(2500) AS LONG
    LOCAL width AS LONG
    LOCAL height AS LONG
    LOCAL idx AS LONG
    LOCAL lineStr AS STRING
    LOCAL pct AS LONG
    LOCAL pctStr AS STRING
    LOCAL sliceChar AS STRING
    LOCAL tempStr AS STRING
    LOCAL dx AS LONG
    LOCAL dy AS LONG
    LOCAL distSq AS LONG
    LOCAL dx2 AS LONG
    LOCAL dy2 AS LONG
    LOCAL angle AS DOUBLE
    LOCAL holeRadius AS LONG
    PRINT "============================================"
    PRINT "          ASCII PIE CHART"
    PRINT "============================================"
    PRINT ""
    PRINT "Simple proportional bar (linear pie):"
    PRINT ""
    n = 5
    data(0) = 30
    data(1) = 20
    data(2) = 25
    data(3) = 15
    data(4) = 10
    total = 0
    FOR i = 0 TO n - 1
        total = total + data(i)
    NEXT i
    IF total < 1 THEN
        total = 1
    END IF
    FOR i = 0 TO n - 1
        pct = data(i) * 100 / total
        pctStr = STR$(pct)
        lineStr = " Slice " + STR$(i) + ": "
        FOR j = 1 TO data(i) * 40 / total
            lineStr = lineStr + "#"
        NEXT j
        lineStr = lineStr + " " + STR$(data(i)) + " (" + pctStr + "%)"
        PRINT lineStr
    NEXT i
    PRINT ""
    PRINT "============================================"
    PRINT "     CIRCULAR PIE CHART (text grid)"
    PRINT "============================================"
    PRINT ""
    width = 50
    height = 25
    radius = 10
    cx = 25
    cy = 12
    FOR i = 0 TO height * width - 1
        grid(i) = 0
    NEXT i
    n = 4
    data(0) = 35
    data(1) = 25
    data(2) = 20
    data(3) = 20
    total = 0
    FOR i = 0 TO n - 1
        total = total + data(i)
    NEXT i
    IF total < 1 THEN
        total = 1
    END IF
    FOR i = 0 TO n - 1
        angles(i) = data(i) * 360 / total
    NEXT i
    FOR x = 0 TO width - 1
        FOR y = 0 TO height - 1
            dx = x - cx
            dy = y - cy
            IF dx < 0 THEN
                dx = 0 - dx
            END IF
            IF dy < 0 THEN
                dy = 0 - dy
            END IF
            distSq = dx * dx + dy * dy
            IF distSq <= radius * radius AND distSq >= (radius - 2) * (radius - 2) THEN
                idx = y * width + x
                grid(idx) = 9
            END IF
        NEXT x
    NEXT y
    FOR y = 0 TO height - 1
        lineStr = ""
        FOR x = 0 TO width - 1
            idx = y * width + x
            IF grid(idx) = 9 THEN
                lineStr = lineStr + "#"
            ELSE
                lineStr = lineStr + " "
            END IF
        NEXT x
        PRINT lineStr
    NEXT y
    PRINT ""
    PRINT "============================================"
    PRINT "     SEGMENTED PIE (filled sectors)"
    PRINT "============================================"
    PRINT ""
    radius = 8
    cx = 20
    cy = 10
    FOR y = 0 TO height - 1
        lineStr = ""
        FOR x = 0 TO width - 1
            dx = x - cx
            dy = y - cy
            IF dx < 0 THEN
                dx = 0 - dx
            END IF
            IF dy < 0 THEN
                dy = 0 - dy
            END IF
            distSq = dx * dx + dy * dy
            IF distSq <= radius * radius THEN
                startAngle = 0
                sliceChar = "."
                FOR i = 0 TO n - 1
                    endAngle = startAngle + angles(i)
                    IF endAngle > 360 THEN
                        endAngle = 360
                    END IF
                    angle = 0
                    IF dx > 0 THEN
                        angle = ArcTan(dy / dx) * 180 / 3.14159
                    ELSE
                        IF dx < 0 THEN
                            angle = ArcTan(dy / 0 - dx) * 180 / 3.14159 + 180
                        ELSE
                            IF dy > 0 THEN
                                angle = 90
                            ELSE
                                IF dy < 0 THEN
                                    angle = 270
                                END IF
                            END IF
                        END IF
                    END IF
                    IF angle < 0 THEN
                        angle = angle + 360
                    END IF
                    IF angle >= startAngle AND angle < endAngle THEN
                        IF i = 0 THEN sliceChar = "A"
                        IF i = 1 THEN sliceChar = "B"
                        IF i = 2 THEN sliceChar = "C"
                        IF i = 3 THEN sliceChar = "D"
                    END IF
                    startAngle = endAngle
                NEXT i
                lineStr = lineStr + sliceChar
            ELSE
                lineStr = lineStr + " "
            END IF
        NEXT x
        PRINT lineStr
    NEXT y
    PRINT ""
    PRINT "============================================"
    PRINT "     DONUT CHART (circle with hole)"
    PRINT "============================================"
    PRINT ""
    radius = 10
    holeRadius = 4
    cx = 15
    cy = 12
    n = 3
    data(0) = 50
    data(1) = 30
    data(2) = 20
    total = 0
    FOR i = 0 TO n - 1
        total = total + data(i)
    NEXT i
    IF total < 1 THEN
        total = 1
    END IF
    FOR i = 0 TO n - 1
        angles(i) = data(i) * 360 / total
    NEXT i
    FOR y = 4 TO 20
        lineStr = ""
        FOR x = 5 TO 25
            dx = x - cx
            dy = y - cy
            IF dx < 0 THEN
                dx = 0 - dx
            END IF
            IF dy < 0 THEN
                dy = 0 - dy
            END IF
            distSq = dx * dx + dy * dy
            IF distSq <= radius * radius AND distSq >= holeRadius * holeRadius THEN
                startAngle = 0
                sliceChar = "."
                FOR i = 0 TO n - 1
                    endAngle = startAngle + angles(i)
                    IF endAngle > 360 THEN
                        endAngle = 360
                    END IF
                    angle = 0
                    dx2 = x - cx
                    dy2 = y - cy
                    IF dx2 <> 0 THEN
                        angle = ArcTan(dy2 / dx2) * 180 / 3.14159
                    ELSE
                        IF dy2 > 0 THEN
                            angle = 90
                        ELSE
                            angle = 270
                        END IF
                    END IF
                    IF dx2 < 0 THEN
                        angle = angle + 180
                    END IF
                    IF angle < 0 THEN
                        angle = angle + 360
                    END IF
                    IF angle >= startAngle AND angle < endAngle THEN
                        IF i = 0 THEN sliceChar = "#"
                        IF i = 1 THEN sliceChar = "@"
                        IF i = 2 THEN sliceChar = "*"
                    END IF
                    startAngle = endAngle
                NEXT i
                lineStr = lineStr + sliceChar
            ELSE
                IF distSq > radius * radius THEN
                    lineStr = lineStr + " "
                ELSE
                    lineStr = lineStr + " "
                END IF
            END IF
        NEXT x
        PRINT lineStr
    NEXT y
    PRINT ""
    PRINT "============================================"
    PRINT "     PIE CHART LEGEND"
    PRINT "============================================"
    PRINT ""
    FOR i = 0 TO n - 1
        pct = data(i) * 100 / total
        IF i = 0 THEN sliceChar = "#"
        IF i = 1 THEN sliceChar = "@"
        IF i = 2 THEN sliceChar = "*"
        lineStr = " " + sliceChar + " Slice " + STR$(i) + ": " + STR$(data(i)) + " (" + STR$(pct) + "%)"
        PRINT lineStr
    NEXT i
    PRINT ""
    PRINT "Pie chart demonstration complete"
    FUNCTION = 0
END FUNCTION
