Manual Harmonic Patterns - With interactive inputs
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed

//   __    __            __       __  __                  __       __                        __      __    __              __      _______             __    __                                          __ 
//  /  |  /  |          /  |  _  /  |/  |                /  \     /  |                      /  |    /  \  /  |            /  |    /       \           /  \  /  |                                        /  |
//  $$ |  $$ |  ______  $$ | / \ $$ |$$ |____    ______  $$  \   /$$ | __    __   _______  _$$ |_   $$  \ $$ |  ______   _$$ |_   $$$$$$$  |  ______  $$  \ $$ |  ______   _____  ____    ______    ____$$ |
//  $$ |__$$ | /      \ $$ |/$  \$$ |$$      \  /      \ $$$  \ /$$$ |/  |  /  | /       |/ $$   |  $$$  \$$ | /      \ / $$   |  $$ |__$$ | /      \ $$$  \$$ | /      \ /     \/    \  /      \  /    $$ |
//  $$    $$ |/$$$$$$  |$$ /$$$  $$ |$$$$$$$  |/$$$$$$  |$$$$  /$$$$ |$$ |  $$ |/$$$$$$$/ $$$$$$/   $$$$  $$ |/$$$$$$  |$$$$$$/   $$    $$< /$$$$$$  |$$$$  $$ | $$$$$$  |$$$$$$ $$$$  |/$$$$$$  |/$$$$$$$ |
//  $$$$$$$$ |$$    $$ |$$ $$/$$ $$ |$$ |  $$ |$$ |  $$ |$$ $$ $$/$$ |$$ |  $$ |$$      \   $$ | __ $$ $$ $$ |$$ |  $$ |  $$ | __ $$$$$$$  |$$    $$ |$$ $$ $$ | /    $$ |$$ | $$ | $$ |$$    $$ |$$ |  $$ |
//  $$ |  $$ |$$$$$$$$/ $$$$/  $$$$ |$$ |  $$ |$$ \__$$ |$$ |$$$/ $$ |$$ \__$$ | $$$$$$  |  $$ |/  |$$ |$$$$ |$$ \__$$ |  $$ |/  |$$ |__$$ |$$$$$$$$/ $$ |$$$$ |/$$$$$$$ |$$ | $$ | $$ |$$$$$$$$/ $$ \__$$ |
//  $$ |  $$ |$$       |$$$/    $$$ |$$ |  $$ |$$    $$/ $$ | $/  $$ |$$    $$/ /     $$/   $$  $$/ $$ | $$$ |$$    $$/   $$  $$/ $$    $$/ $$       |$$ | $$$ |$$    $$ |$$ | $$ | $$ |$$       |$$    $$ |
//  $$/   $$/  $$$$$$$/ $$/      $$/ $$/   $$/  $$$$$$/  $$/      $$/  $$$$$$/  $$$$$$$/     $$$$/  $$/   $$/  $$$$$$/     $$$$/  $$$$$$$/   $$$$$$$/ $$/   $$/  $$$$$$$/ $$/  $$/  $$/  $$$$$$$/  $$$$$$$/ 
//                                                                                                                                                                                                          
//                                                                                                                                                                                                          
//
//@version=5
indicator("Manual Harmonic Patterns - With interactive inputs", overlay=true)
import HeWhoMustNotBeNamed/eHarmonicpatternsExtended/6 as hp
import HeWhoMustNotBeNamed/utils/1 as pa

x = input.price(0,'X',group='XABCD', inline=  '1', confirm=true)
xBarTime = input.time(0,'',group='XABCD', inline=  '1', confirm=true)
a = input.price(0,'A',group='XABCD', inline=  '2', confirm=true)
aBarTime = input.time(0,'',group='XABCD', inline=  '2', confirm=true)
b = input.price(0,'B',group='XABCD', inline=  '3', confirm=true)
bBarTime = input.time(0,'',group='XABCD', inline=  '3', confirm=true)
c = input.price(0,'C',group='XABCD', inline=  '4', confirm=true)
cBarTime = input.time(0,'',group='XABCD', inline=  '4', confirm=true)
d = input.price(0,'D',group='XABCD', inline=  '5', confirm=true)
dBarTime = input.time(0,'',group='XABCD', inline=  '5', confirm=true)

showXABCD = input.bool(true, title='Show XABCD', group='Display', inline='showHide')
showRatios = input.bool(true, title='Show Ratios', group='Display', inline='showHide')

fillMajorTriangles = input.bool(true, title="Fill XAB/BCD", group="Display", inline="fill1")
majorFillTransparency = input.int(70, step=5, title="", group="Display", inline="fill1")
fillMinorTriangles = input.bool(true, title="Fill ABC/XBD", group="Display", inline="fill2")
minorFillTransparency = input.int(90, step=5, title="", group="Display", inline="fill2")

errorPercent = input.int(8, group="Miscellaneous")
przType = input.string("XAD Range", "PRZ Type", options=["XAD Range", "BCD+XAD Range"], group='Miscellaneous')
useCombinedPrz = (przType == "BCD+XAD Range")
patternColor = input.color(color.purple, group="Miscellaneous")

classic = input.bool(true, title="Classic Patterns", group="Category", inline="ca")
anti = input.bool(true, title="Anti/Alternate Patterns", group="Category", inline="ca")
nonStandard = input.bool(true, title="Nonstandard",  group="Category", inline="ca")

gartley = input.bool(true, title='Gartley       ', group='Classic Patterns', inline="c1")
bat = input.bool(true, title='Bat      ', group='Classic Patterns', inline="c1")
butterfly = input.bool(true, title='Butterfly   ', group='Classic Patterns', inline="c1")
crab = input.bool(true, title='Crab', group='Classic Patterns', inline="c1")
deepCrab = input.bool(true, title='Deep Crab   ', group='Classic Patterns', inline="c2")
cypher = input.bool(true, title='Cypher   ', group='Classic Patterns', inline="c2")
shark = input.bool(true, title='Shark      ', group='Classic Patterns', inline="c2")
nenStar = input.bool(true, title='Nenstar', group='Classic Patterns', inline="c2")

antiNenStar = input.bool(true, title='Anti Nenstar   ', group='Anti Patterns', inline="a1")
antiShark = input.bool(true, title='Anti Shark', group='Anti Patterns', inline="a1")
antiCypher = input.bool(true, title='Anti Cypher ', group='Anti Patterns', inline="a1")
antiCrab = input.bool(true, title='Anti Crab', group='Anti Patterns', inline="a1")
antiButterfly = input.bool(true, title='Anti Butterfly', group='Anti Patterns', inline="a2")
antiBat = input.bool(true, title='Anti Bat  ', group='Anti Patterns', inline="a2")
antiGartley = input.bool(true, title='Anti Gartley', group='Anti Patterns', inline="a2")
navarro200 = input.bool(true, title='Navarro 200', group='Anti Patterns', inline="a2")

fiveZero = input.bool(true, title='Five Zero', group='Non Standard', inline="a1")
threeDrives = input.bool(true, title='Three Drives', group='Non Standard', inline="a1")
whiteSwann = input.bool(true, title='White Swann', group='Non Standard', inline="a1")
blackSwann = input.bool(true, title='Black Swann', group='Non Standard', inline="a1")
seaPony = input.bool(true, title='Sea Pony', group='Non Standard', inline="a2")
leonardo = input.bool(true, title='Leonardo', group='Non Standard', inline="a2")
oneTwoOne = input.bool(true, title='121', group='Non Standard', inline="a2")
snorm = input.bool(true, title='Snorm', group='Non Standard', inline="a2")
totalPattern = input.bool(true, title='Total', group='Non Standard', inline="a2")

NUMBER_OF_PATTERNS = 25
enableGartley = classic and gartley
enableBat = classic and bat
enableButterfly = classic and butterfly
enableCrab = classic and crab
enableDeepCrab = classic and deepCrab
enableCypher = classic and cypher
enableShark = classic and shark
enableNenStar = classic and nenStar

enableAntiNenStar = anti and antiNenStar
enableAntiShark = anti and antiShark
enableAntiCypher = anti and antiCypher
enableAntiCrab = anti and antiCrab
enableAntiButterfly = anti and antiButterfly
enableAntiBat = anti and antiBat
enableAntiGartley = anti and antiGartley
enableNavarro200 = anti and navarro200
enableFiveZero = nonStandard and fiveZero
enableThreeDrives = nonStandard and threeDrives
enableWhiteSwann = nonStandard and whiteSwann
enableBlackSwann = nonStandard and blackSwann
enableSeaPony = nonStandard and seaPony
enableLeonardo = nonStandard and leonardo
enableOneTwoOne = nonStandard and oneTwoOne
enableSnorm = nonStandard and snorm
enableTotal = nonStandard and totalPattern

flags = array.new_bool()
array.push(flags, enableGartley)
array.push(flags, enableCrab)
array.push(flags, enableDeepCrab)
array.push(flags, enableBat)
array.push(flags, enableButterfly)
array.push(flags, enableShark)
array.push(flags, enableCypher)
array.push(flags, enableNenStar)

array.push(flags, enableAntiNenStar)
array.push(flags, enableAntiShark)
array.push(flags, enableAntiCypher)
array.push(flags, enableAntiCrab)
array.push(flags, enableAntiButterfly)
array.push(flags, enableAntiBat)
array.push(flags, enableAntiGartley)
array.push(flags, enableNavarro200)

array.push(flags, enableFiveZero)
array.push(flags, enableThreeDrives)
array.push(flags, enableWhiteSwann)
array.push(flags, enableBlackSwann)
array.push(flags, enableSeaPony)
array.push(flags, enableLeonardo)
array.push(flags, enableOneTwoOne)
array.push(flags, enableSnorm)
array.push(flags, enableTotal)

get_prz_range(x, a, b, c, patterns, errorPercent, prc_entry=0, prc_stop=0)=>
    [boxStart, boxEnd] = if useCombinedPrz
        hp.get_prz_range(x, a, b, c, patterns, errorPercent, prc_entry, prc_stop)
    else
        hp.get_prz_range_xad(x, a, b, c, patterns, errorPercent, prc_entry, prc_stop)
    [boxStart, boxEnd]
    
f_draw_pattern_line(y1, y2, x1, x2, lineColor, width, style) =>
    targetLine = line.new(y1=y1, y2=y2, x1=x1, x2=x2, color=lineColor, width=width, style=style)
    targetLine

f_draw_pattern_label(y, x, txt, textcolor, style, yloc, size) =>
    targetLabel = label.new(y=y, x=x, text=txt, textcolor=textcolor, style=style, yloc=yloc, size=size)
    targetLabel

draw_xabcd(x, a, b, c, d, xBar, aBar, bBar, cBar, dBar, dir, labelColor, patterns) =>
    hasPatterns = array.includes(patterns, true), 
    isCypher = array.get(patterns, 6)
    xa = f_draw_pattern_line(y1=x, y2=a, x1=xBar, x2=aBar, lineColor=labelColor, width=1, style=line.style_solid)
    ab = f_draw_pattern_line(y1=a, y2=b, x1=aBar, x2=bBar, lineColor=labelColor, width=1, style=line.style_solid)
    bc = f_draw_pattern_line(y1=b, y2=c, x1=bBar, x2=cBar, lineColor=labelColor, width=1, style=line.style_solid)
    cd = f_draw_pattern_line(y1=c, y2=d, x1=cBar, x2=dBar, lineColor=labelColor, width=1, style=line.style_solid)
    xb = f_draw_pattern_line(y1=x, y2=b, x1=xBar, x2=bBar, lineColor=labelColor, width=1, style=line.style_dashed)
    bd = f_draw_pattern_line(y1=b, y2=d, x1=bBar, x2=dBar, lineColor=labelColor, width=1, style=line.style_dashed)
    ac = f_draw_pattern_line(y1=a, y2=c, x1=aBar, x2=cBar, lineColor=labelColor, width=1, style=line.style_dotted)
    xd = f_draw_pattern_line(y1=x, y2=d, x1=xBar, x2=dBar, lineColor=labelColor, width=1, style=line.style_dotted)

    if(fillMajorTriangles and hasPatterns)
        xaab = linefill.new(xa, ab, color.new(labelColor, majorFillTransparency))
        xbab = linefill.new(xb, ab, color.new(labelColor, majorFillTransparency))
        bccd = linefill.new(bc, cd, color.new(labelColor, majorFillTransparency))
        bdcd = linefill.new(bd, cd, color.new(labelColor, majorFillTransparency))

    if(fillMinorTriangles and hasPatterns)
        abbc = linefill.new(ab, bc, color.new(labelColor, minorFillTransparency))
        acbc = linefill.new(ac, bc, color.new(labelColor, minorFillTransparency))
        xbbd = linefill.new(xb, bd, color.new(labelColor, minorFillTransparency))
        xdbd = linefill.new(xd, bd, color.new(labelColor, minorFillTransparency))

    if showXABCD
        gap = ta.tr/10
        xLabel = f_draw_pattern_label(y=(dir>0?x-gap:x+gap), x=xBar, txt='X', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        aLabel = f_draw_pattern_label(y=(dir>0?a+gap:a-gap), x=aBar, txt='A', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        bLabel = f_draw_pattern_label(y=(dir>0?b-gap:b+gap), x=bBar, txt='B', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        cLabel = f_draw_pattern_label(y=(dir>0?c+gap:c-gap), x=cBar, txt='C', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        dLabel = f_draw_pattern_label(y=(dir>0?d-gap:d+gap), x=dBar, txt='D', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
    if showRatios
        xabRatio = math.round(math.abs(a - b) / math.abs(x - a), 3)
        xabRatioBar = (xBar + bBar) / 2

        abcRatio = math.round(math.abs(b - c) / math.abs(a - b), 3)
        abcRatioBar = (aBar + cBar) / 2

        bcdRatio = math.round(math.abs(c - d) / math.abs(b - c), 3)
        bcdRatioBar = (bBar + dBar) / 2

        xadRatio = math.round(math.abs(a - d) / math.abs(x - a), 3)
        xadRatioBar = (xBar + dBar) / 2

        axcRatio = math.round(math.abs(x - c) / math.abs(x - a), 3)
        xcdRatio = math.round(math.abs(d - c) / math.abs(x - c), 3)

        xabRatioPrice = line.get_price(xb, xabRatioBar)
        abcRatioPrice = line.get_price(ac, abcRatioBar)
        bcdRatioPrice = line.get_price(bd, bcdRatioBar)
        xadRatioPrice = line.get_price(xd, xadRatioBar)

        abcRatioLabelText = str.tostring(abcRatio) + '(ABC)' + (isCypher ? '\n' + str.tostring(axcRatio) + '(AXC)' : '')
        xadRatioLabelText = str.tostring(xadRatio) + '(XAD)' + (isCypher ? '\n' + str.tostring(xcdRatio) + '(XCD)' : '')
        xabLabel = f_draw_pattern_label(y=xabRatioPrice, x=xabRatioBar, txt=str.tostring(xabRatio) + '(XAB)', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        abcLabel = f_draw_pattern_label(y=abcRatioPrice, x=abcRatioBar, txt=abcRatioLabelText, textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        bcdLabel = f_draw_pattern_label(y=bcdRatioPrice, x=bcdRatioBar, txt=str.tostring(bcdRatio) + '(BCD)', textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)
        xadLabel = f_draw_pattern_label(y=xadRatioPrice, x=xadRatioBar, txt=xadRatioLabelText, textcolor=labelColor, style=label.style_none, yloc=yloc.price, size=size.small)


f_draw_entry_box(y1, y2, x1, linecolor, labelColor, labelText) =>
    x2 = x1 + 20
    y = (y1 + y2) / 2
    xloc = xloc.bar_index
    transp = 70
    entryBox = box.new(x1, y1, x2, y2, linecolor, 1, line.style_dotted, xloc=xloc, bgcolor=color.new(labelColor, transp), text=labelText,
                         text_color=labelColor, text_size=size.small)

var printed = false
patternLabels = hp.getSupportedPatterns()
if(barstate.islast and not printed)
    patterns = hp.isHarmonicPattern(x, a, b, c, d, flags, errorPercent = errorPercent)

    int xBar = na
    int aBar = na
    int bBar = na
    int cBar = na
    int dBar = na
    
    offset = 0
    while(na(xBar) or na(aBar) or na(bBar) or na(cBar) or na(dBar))
        bartime = time[offset]
        if(na(xBar) and bartime == xBarTime)
            xBar := bar_index - offset
        if(na(aBar) and bartime == aBarTime)
            aBar := bar_index - offset
        if(na(bBar) and bartime == bBarTime)
            bBar := bar_index - offset
        if(na(cBar) and bartime == cBarTime)
            cBar := bar_index - offset
        if(na(dBar) and bartime == dBarTime)
            dBar := bar_index - offset
        offset+=1
                         
    dir = c > d? 1 : -1
    draw_xabcd(x, a, b, c, d, xBar, aBar, bBar, cBar, dBar, dir, patternColor, patterns)
    [dStart, dEnd] = get_prz_range(x, a, b, c, patterns, errorPercent)
    lbl = pa.getConsolidatedLabel(patterns, patternLabels)
    f_draw_entry_box(dStart, dEnd, dBar+5, patternColor, patternColor, lbl) 
    printed := true