LibraryPrivateUsage001
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © LonesomeTheBlue

//@version=5

// @description This library is used for math operations. 
library("LibraryPrivateUsage001")

// @function checks if the array elements (which index is smaller than end) is smaller than the value ylv
// @param ylv value to compare array elements
// @param end last index of the array elements
// @param arr the array pointer
// @returns true if none of the elements is smaller than ylv, otherwise returns false
bIsF(float ylv, float end, float [] arr) =>
    array.min(array.slice(arr, 1, math.round(end))) >= ylv
    
// @function checks if the array elements (which index is smaller than end) is greater than the value ylv
// @param ylv value to compare array elements
// @param end last index of the array elements
// @param arr the array pointer
// @returns true if none of the elements is greater than ylv, otherwise returns false
tIsF(float ylv, float end, float [] arr) =>
    array.max(array.slice(arr, 1, math.round(end))) <= ylv
    
// @function checks if the array element is between v1 and v2
// @param rates_array array that keeps float elements
// @param index then number of elements in the array to compare
// @param v1 and v2 the values to compare with the array element
// @returns true if the array element is between v1 and v2
isfine1(float [] rates_array, int index, float v1, float v2) =>
    (array.get(rates_array, index) >= v1 and array.get(rates_array, index) <= v2)

// @function checks if l1/l2 is between v1 and v2
// @param l1 float
// @param l2 float
// @param index then number of elements in the array to compare
// @param v1 and v2 the values to compare with l1/l2
// @returns true if l1/l2is between v1 and v2  
isFine(float d, float v1, float v2) =>
    (d >= v1 and d <= v2)

// @function assigns maximum and minimum values to the array mima
// @param mima is the array to keep max/min
// @param c1 first var of part1
// @param c2 second var of part1
// @param a1 first var of part2
// @param a2 second var of part2
// @returns none
export getRMinmax1(float [] mima, float c1, float c2, float a1, float a2) =>
    array.set(mima, 0,  math.min(math.max(c1, c2), math.max(a1, a2)))
    array.set(mima, 1,  math.max(math.min(c1, c2), math.min(a1, a2)))

// @function assigns maximum and minimum values to the array mima
// @param mima is the array to keep max/min
// @param c1 first var
// @param c2 second var 
// @returns none
export getRMinmax2(float [] mima, float c1, float c2) =>
    array.set(mima, 0,  math.max(c1, c2))
    array.set(mima, 1,  math.min(c1, c2))
    
// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType10(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        (array.get(allvalues, 9) < array.get(allvalues, 10) and 
           (isFine((array.get(allvalues, 3) - array.get(allvalues, 4)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(allvalues, 12), array.get(allvalues, 13))) and 
           (isFine((array.get(allvalues, 3) - array.get(allvalues, 2)) / (array.get(allvalues, 1) - array.get(allvalues, 2)), array.get(allvalues, 15), array.get(allvalues, 16))) and 
           ((array.get(allvalues, 1) - array.get(allvalues, 0)) / (array.get(allvalues, 1) - array.get(allvalues, 2)) > 1.) and 
           array.get(allvalues, 5) < math.max(array.get(allvalues, 1), array.get(allvalues, 3))) ? bIsF(math.max(array.get(allvalues, 1), array.get(allvalues, 3)), bar_index - array.get(allvalues, 8), arr) : false

// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType11(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        (array.get(allvalues, 9) > array.get(allvalues, 10) and 
          (isFine((array.get(allvalues, 3) - array.get(allvalues, 4)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(allvalues, 12), array.get(allvalues, 13))) and 
          (isFine((array.get(allvalues, 3) - array.get(allvalues, 2)) / (array.get(allvalues, 1) - array.get(allvalues, 2)), array.get(allvalues, 15), array.get(allvalues, 16))) and 
          ((array.get(allvalues, 1) - array.get(allvalues, 0)) / (array.get(allvalues, 1) - array.get(allvalues, 2)) > 1.) and 
          array.get(allvalues, 5) > math.min(array.get(allvalues, 1), array.get(allvalues, 3))) ? tIsF(math.min(array.get(allvalues, 1), array.get(allvalues, 3)), bar_index - array.get(allvalues, 8), arr) : false

// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType12(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        ((math.abs(array.get(allvalues, 2) - array.get(allvalues, 1)) > math.abs(array.get(allvalues, 2) - array.get(allvalues, 3))) and 
          (isFine((array.get(allvalues, 2) - array.get(allvalues, 3)) / (array.get(allvalues, 4) - array.get(allvalues, 3)), array.get(allvalues, 15), array.get(allvalues, 16))) and 
          (array.get(allvalues, 2) > array.get(allvalues, 3)) and 
          (array.get(allvalues, 5) < array.get(allvalues, 3)) and 
          (array.get(allvalues, 6) > array.get(allvalues, 14))) ? bIsF(math.max(array.get(allvalues, 1), array.get(allvalues, 3)), bar_index - array.get(allvalues, 7), arr) : false

// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType13(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        ((math.abs(array.get(allvalues, 2) - array.get(allvalues, 1)) > math.abs(array.get(allvalues, 2) - array.get(allvalues, 3))) and 
          (isFine((array.get(allvalues, 2) - array.get(allvalues, 3)) / (array.get(allvalues, 4) - array.get(allvalues, 3)), array.get(allvalues, 15), array.get(allvalues, 16))) and 
          (array.get(allvalues, 2) < array.get(allvalues, 3)) and 
          (array.get(allvalues, 5) > array.get(allvalues, 3)) and 
          (array.get(allvalues, 6) > array.get(allvalues, 14))) ? tIsF(math.min(array.get(allvalues, 1), array.get(allvalues, 3)), bar_index - array.get(allvalues, 7), arr) : false

// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType14(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        (isFine((array.get(allvalues, 0) - array.get(allvalues, 1)) / (array.get(allvalues, 2) - array.get(allvalues, 1)), array.get(allvalues, 17), array.get(allvalues, 18))) and
         (isFine((array.get(allvalues, 4) - array.get(allvalues, 3)) / (array.get(allvalues, 2) - array.get(allvalues, 3)), array.get(allvalues, 17), array.get(allvalues, 18))) and
         (isFine((array.get(allvalues, 1) - array.get(allvalues, 2)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(allvalues, 15), array.get(allvalues, 16))) and
         array.get(allvalues, 5) < math.min(array.get(allvalues, 1), array.get(allvalues, 3)) ? bIsF(array.get(allvalues, 3), bar_index - array.get(allvalues, 7), arr) : false

// @function checks if thiscond is true and elements of rates array is between the elements of rates_array
// @param thiscond to check if it's true
// @param rates_array to get values to compare
// @param arr keeps the values to compare them with the elements of rates_array
// @returns true if all conditions met
export checkType15(bool thiscond, float [] allvalues, float [] arr) =>
    if thiscond
        (isFine((array.get(allvalues, 1) - array.get(allvalues, 0)) / (array.get(allvalues, 1) - array.get(allvalues, 2)), array.get(allvalues, 17), array.get(allvalues, 18))) and
         (isFine((array.get(allvalues, 3) - array.get(allvalues, 4)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(allvalues, 17), array.get(allvalues, 18))) and
         (isFine((array.get(allvalues, 1) - array.get(allvalues, 2)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(allvalues, 15), array.get(allvalues, 16))) and
         array.get(allvalues, 5) > math.max(array.get(allvalues, 1), array.get(allvalues, 3)) ? tIsF(array.get(allvalues, 3), bar_index - array.get(allvalues, 7), arr) : false


// @function checks conditions and if the conditions met then get max/min values and assign them to elements mima array
// @param vals array to to get values
// @param allina array of constant values
// @param index array pointer
// @returns minmax values in a array if all conditions met
CheckRtype1(float [] vals, float [] allina, int index) =>
    mima = array.new_float(2, na)
    if isFine((array.get(vals, 1) - array.get(vals, 2)) / (array.get(vals, 1) - array.get(vals, 0)), array.get(allina, 22 * (index - 1)), array.get(allina, 22 * (index - 1) + 1)) and
       isFine((array.get(vals, 3) - array.get(vals, 2)) / (array.get(vals, 1) - array.get(vals, 2)), array.get(allina, 22 * (index - 1) + 2), array.get(allina, 22 * (index - 1) + 3))
        p0 = array.get(vals, 0)
        p1 = array.get(vals, 1)
        p2 = array.get(vals, 2)
        p3 = array.get(vals, 3)
        c1 = p3 - array.get(allina, 22 * (index - 1) + 4) * (p3 - p2)
        c2 = p3 - array.get(allina, 22 * (index - 1) + 5) * (p3 - p2)
        a1 = p1 - array.get(allina, 22 * (index - 1) + 6) * (p1 - p0)
        a2 = p1 - array.get(allina, 22 * (index - 1) + 7) * (p1 - p0)
        getRMinmax1(mima, c1, c2, a1, a2)
        
    [array.get(mima, 0), array.get(mima, 1)]

// @function checks conditions and if the conditions met then get max/min values and assign them to elements mima array
// @param vals array to to get values
// @param allina array of constant values
// @param index array pointer
// @returns minmax values in a array if all conditions met
CheckRtype2(float [] vals, float [] allina, int index) =>
    mima = array.new_float(2, na)
    if isFine((array.get(vals, 2) - array.get(vals, 1)) / (array.get(vals, 0) - array.get(vals, 1)), array.get(allina, 22 * (index - 1)), array.get(allina, 22 * (index - 1) + 1)) and
       isFine((array.get(vals, 0) - array.get(vals, 3)) / (array.get(vals, 0) - array.get(vals, 1)), array.get(allina, 22 * (index - 1) + 8), array.get(allina, 22 * (index - 1) + 9))
        p2 = array.get(vals, 0) // x
        p1 = array.get(vals, 3) // c
        c1 = p1 - array.get(allina, 22 * (index - 1) + 10) * (p1 - p2)
        c2 = p1 - array.get(allina, 22 * (index - 1) + 11) * (p1 - p2)
        getRMinmax2(mima, c1, c2)
    
    [array.get(mima, 0), array.get(mima, 1)]
    
// @function checks mima array and if conditions met assigns the elements of pre_loc array
// @param pre_loc keeps the elements that is set when conditions met 
// @param arr is an array which keeps the values to compare
// @param index is an integer value that is used as index while assigning values to pre_loc array
// @returns mima is the array that keeps max/min values
setPPL(float [] pre_loc, float [] arr, int index, int dir, float mima) =>
    if array.size(pre_loc) == 0
        for x = 0 to 7
            array.push(pre_loc, array.get(arr, index + x))
        array.unshift(pre_loc, mima)
    else
        if (dir == 1 and array.get(pre_loc, 0) > mima) or
           (dir == -1 and array.get(pre_loc, 0) < mima)
            for x = 1 to 8
                array.set(pre_loc, x, array.get(arr, index + x - 1))
            array.set(pre_loc, 0, mima)

// @function checks arr array and if distance is greater than mindis
// @param ylv is used to check level
// @param arr is an array which keeps the values to compare
// @param mindis is the distance
// @param index is start value for the loop
// @returns the location in arr
export findmaxup(float [] arr, float ylv, float mindis, int index)=>
    ret = 0
    for x = index to (index < array.size(arr) ? array.size(arr) - 1 : na) by 2
        if array.get(arr, x) < ylv or (array.get(arr, x) - ylv >= mindis)
            ret := array.get(arr, x) < ylv ? 0 : x
            break
    ret

// @function checks arr array and if distance is greater than mindis
// @param ylv is used to check level
// @param arr is an array which keeps the values to compare
// @param mindis is the distance
// @param index is start value for the loop
// @returns the location in arr
export findmaxdown(float [] arr, float ylv, float mindis, int index)=>
    ret = 0
    for x = index to (index < array.size(arr) ? array.size(arr) - 1 : na) by 2
        if array.get(arr, x) > ylv or (ylv - array.get(arr, x) >= mindis)
            ret := array.get(arr, x) > ylv ? 0 : x
            break
    ret
    
// @function used find right level
// @param x and xl is used for x
// @param a and al is used for a
// @returns xl for x
export fxl(float x, float xl, float a, float al, float b) =>
    len = al - xl
    float slope = (a - x) / len
    float vline = a - slope
    ret = xl
    for t = 1 to len by 1
        if slope > 0 and vline < b or slope < 0 and vline > b
            ret := al - t
            break
        vline := vline - slope
    math.round(ret)

// @function used find minmax value from the array
// @param mvar is used to search which part
// @returns levels and ind
export gmm(float [] marray, int mvar) =>
    float ma = na
    float mi = na
    int ind = mvar == 1 ? array.indexof(marray, array.min(marray)) : array.indexof(marray, array.max(marray))
    
    if ind >= 0
        ind -= (ind % 2)
        ma := array.get(marray, ind)
        mi := array.get(marray, ind + 1)
        ind := math.round(ind / 2)
   
    [ma, mi, ind]

// @function checks checksmType using all values and the const arrays
// @param mc_arr keeps c values
// @param allvalues keeps all values variables
// @param const_array keeps constant values
// @param mh_arr keeps h values
// @param mk_arr keeps l values
// @returns dloc variable if all conditions met
export checksmType(float [] allvalues, float [] const_array, float [] mc_arr, float [] mh_arr, float [] ml_arr) =>
    float Dloc = na
    if isFine((array.get(allvalues, 2) - array.get(allvalues, 3)) / (array.get(allvalues, 2) - array.get(allvalues, 1)), array.get(const_array, 0), array.get(const_array, 1)) and 
       isFine((array.get(allvalues, 3) - array.get(allvalues, 4)) / (array.get(allvalues, 3) - array.get(allvalues, 2)), array.get(const_array, 0), array.get(const_array, 1)) and 
       (array.get(allvalues, 1) - array.get(allvalues, 0)) / (array.get(allvalues, 1) - array.get(allvalues, 2)) > 1.
        // check first part
        slp = (array.get(allvalues, 3) - array.get(allvalues, 1)) / (array.get(allvalues, 7) - array.get(allvalues, 5))
        ln = array.get(allvalues, 1) + slp
        firstpart = true
        len1 = math.round(bar_index - array.get(allvalues, 5))
        len12 = bar_index - array.get(allvalues, 7)
        ddd = array.get(allvalues, 9) 
        hl_array1 = ddd == 1 ? mh_arr : ml_arr
        for k = len1 - 1 to 1 by 1
            if k > len12
                if array.get(hl_array1, k) * ddd > ln  * ddd
                    firstpart := false
                    break
            else
                if array.get(mc_arr, k) * ddd > ln * ddd
                    firstpart := false
                    break
            ln := ln + slp

        if firstpart
            slp2 = (array.get(allvalues, 4) - array.get(allvalues, 2)) / (array.get(allvalues, 8) - array.get(allvalues, 6))
            ln2 = array.get(allvalues, 2) + slp2
            len22 = math.round(bar_index - array.get(allvalues, 6))
            len23 = bar_index - array.get(allvalues, 8)
            
            Dloc := ln
            hl_array2 = ddd == 1 ? ml_arr : mh_arr
            for k = len22 - 1 to 1 by 1
                if k > len23
                    if array.get(hl_array2, k) * ddd < ln2 * ddd
                        Dloc := na
                        break
                else
                    if array.get(mc_arr, k) * ddd < ln2 * ddd
                        Dloc := na
                        break
                ln2 := ln2 + slp2
    Dloc

// @function removes the element if the condition is not met
// @param cond the condition to check
// @param allina keeps constant values
// @param allinp the array which the function removes the element
// @param add is the index for the arrays
// @returns null
export checkcondtype1(float cond, float [] allina, int [] allinp, int add)=>
    for x = array.size(allinp) - 1 to 0
        index = 22 * (array.get(allinp, x) - 1) + add
        if cond < array.get(allina, index) or cond > array.get(allina, index + 1)
            array.remove(allinp, x)

// @function removes the element if the condition is not met
// @param cond the condition to check
// @param allina keeps constant values
// @param allinp the array which the function removes the element
// @param add is the index for the arrays
// @returns null
export checkcondtype2(float cond, float [] allina, int [] allinp, int add)=>
    for x = array.size(allinp) - 1 to 0
        index = 12 * (array.get(allinp, x) - 1) + add
        if cond < array.get(allina, index) or cond > array.get(allina, index + 1)
            array.remove(allinp, x)
            
// @function checks type1 values and locs using thiscond and the arrays that keeps the values
// @param thiscond keeps if enabled
// @param drw condition to draw
// @param index used as index for the arrays
// @param xtod keeps all values
// @param allina keeps constant values
// @param mpp keep the valus if there is any suitable
// @param mppl keep the locs if there is any suitable
// @param D is the last point
// @param sd keeps the sd
// @returns null
getOnePPType1(bool thiscond, bool drw, int index, float [] xtod, float [] allina, float [] mpp, float [] mppl, float D, int sd)=>
    for x = 0 to (thiscond ? array.size(xtod) - 1 : na) by 10
        [ma, mi] = CheckRtype1(array.from(array.get(xtod, x + 6), array.get(xtod, x + 4), array.get(xtod, x + 2), array.get(xtod, x)), allina, index)
        if mi > 0 and ma >= mi
            if sd == 1 and D < mi or sd == -1 and D > ma
                array.set(mpp, index * 2, ma)
                array.set(mpp, index * 2 + 1, mi)
                if drw
                    setPPL(mppl, xtod, x, sd, (sd == 1 ? mi : ma))
                break

// @function checks type2 values and locs using thiscond and the arrays that keeps the values
// @param thiscond keeps if enabled
// @param drw condition to draw
// @param index used as index for the arrays
// @param xtod keeps all values
// @param allina keeps constant values
// @param mpp keep the valus if there is any suitable
// @param mppl keep the locs if there is any suitable
// @param D is the last point
// @param sd keeps the sd
// @returns null
getOnePPType2(bool thiscond, bool drw, int index, float [] xtod, float [] allina, float [] mpp, float [] mppl, float D, int sd)=>
    for x = 0 to (thiscond ? array.size(xtod) - 1 : na) by 10
        [ma, mi] = CheckRtype2(array.from(array.get(xtod, x + 6), array.get(xtod, x + 4), array.get(xtod, x + 2), array.get(xtod, x)), allina, index)
        if mi > 0 and ma >= mi
            if sd == 1 and D < mi or sd == -1 and D > ma
                array.set(mpp, index * 2, ma)
                array.set(mpp, index * 2 + 1, mi)
                if drw
                    setPPL(mppl, xtod, x, sd, (sd == 1 ? mi : ma))
                break

// @function search all types according to thiscond array
// @param thiscond is the array that keeps if element is enabled
// @param allina keeps constant values
// @param xtod keeps all values
// @param D is the last point
// @param sd keeps the sd
// @param drw keeps if it's enabled or not
// @returns pp and ppl arrays
export getpps(bool [] thiscond, float [] allina, float [] xtod, float D, int sd, bool drw) =>
    pp = array.new_float(40, na)
    ppl = array.new_float(0)
    
    getOnePPType1(array.get(thiscond, 0), drw, 1, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 1), drw, 2, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 2), drw, 3, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 3), drw, 4, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 4), drw, 5, xtod, allina, pp, ppl, D, sd)
    getOnePPType2(array.get(thiscond, 5), drw, 6, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 6), drw, 7, xtod, allina, pp, ppl, D, sd)
    getOnePPType1(array.get(thiscond, 7), drw, 8, xtod, allina, pp, ppl, D, sd)
    
    [pp, ppl]

// @function finds all possible points by using allpoints array
// @param allpoints contains all points in it
// @param side keeps the current side
// @param mplen keeps the length of mp
// @param mploc keeps the location of mp
// @returns apat array that contains possible points
export getthepoints(float [] allpoints, int side, int mplen, int mploc) =>
    // find max X location to search
    lastpoint = 12
    for x = 11 to array.size(allpoints) - 1 by 2
        if bar_index - array.get(allpoints, x) > mploc
            break
        lastpoint := x + 1
    
    apat = array.new_int(0)
    float lastmain = array.get(allpoints, 0)
    float lastp = array.get(allpoints, 2)
    for c = 2 to lastpoint - 8 by 4
        if side == 1 and array.get(allpoints, c - 2) > lastmain or side == -1 and array.get(allpoints, c - 2) < lastmain
            break
        if side == 1 and array.get(allpoints, c) <= lastp or side == -1 and array.get(allpoints, c) >= lastp
            array.push(apat, c)
            array.push(apat, 0)
            array.push(apat, 0)
            array.push(apat, 0)
            array.push(apat, 0)
            lastp := array.get(allpoints, c)
            lastp

    if array.size(apat) >= 5
        for y = 0 to array.size(apat) - 1 by 5
            c = array.get(apat, y)
            lastmain := array.get(allpoints, c)
            lastp := array.get(allpoints, c + 2)
            first = true
            for b = c + 2 to lastpoint - 6 by 4
                if first
                    first := false
                    array.set(apat, y + 1, b)
                else
                    if side == 1 and array.get(allpoints, b - 2) < lastmain or side == -1 and array.get(allpoints, b - 2) > lastmain
                        break
                    if side == 1 and array.get(allpoints, b) >= lastp or side == -1 and array.get(allpoints, b) <= lastp
                        lastp := array.get(allpoints, b)
                        array.push(apat, c)
                        array.push(apat, b)
                        array.push(apat, 0)
                        array.push(apat, 0)
                        array.push(apat, 0)

        for y = 0 to array.size(apat) - 1 by 5
            b = array.get(apat, y + 1)
            if b == 0
                continue
            lastmain := array.get(allpoints, b)
            lastp := array.get(allpoints, b + 2)
            first = true
            c = 0
            for a = b + 2 to lastpoint - 4 by 4
                if first
                    c := array.get(apat, y)
                    first := false
                    array.set(apat, y + 2, a)
                else
                    if side == 1 and array.get(allpoints, a - 2) > lastmain or side == -1 and array.get(allpoints, a - 2) < lastmain
                        break
                    if side == 1 and array.get(allpoints, a) <= lastp or side == -1 and array.get(allpoints, a) >= lastp
                        lastp := array.get(allpoints, a)
                        array.push(apat, c)
                        array.push(apat, b)
                        array.push(apat, a)
                        array.push(apat, 0)
                        array.push(apat, 0)

        for y = 0 to array.size(apat) - 1 by 5
            a = array.get(apat, y + 2)
            if a == 0
                continue
            lastmain := array.get(allpoints, a)
            lastp := array.get(allpoints, a + 2)
            first = true
            b = 0
            c = 0
            for x = a + 2 to lastpoint - 1 by 4
                if first
                    c := array.get(apat, y)
                    b := array.get(apat, y + 1)
                    first := false
                    array.set(apat, y + 3, x)
                    array.set(apat, y + 4, x)
                else
                    if side == 1 and array.get(allpoints, x - 2) < lastmain or side == -1 and array.get(allpoints, x - 2) > lastmain
                        break
                    if side == 1 and array.get(allpoints, x) >= lastp or side == -1 and array.get(allpoints, x) <= lastp
                        lastp := array.get(allpoints, x)
                        array.push(apat, c)
                        array.push(apat, b)
                        array.push(apat, a)
                        array.push(apat, x)
                        array.push(apat, x)

    for y = array.size(apat) - 5 to (array.size(apat) >= 5 ? 0 : na) by 5
        if array.size(apat) < 5
            break

        p1 = array.get(allpoints, array.get(apat, y) + 1)
        p2 = array.get(allpoints, array.get(apat, y + 1) + 1)
        p3 = array.get(allpoints, array.get(apat, y + 2) + 1)
        p4 = array.get(allpoints, array.get(apat, y + 3) + 1)
        if array.get(apat, y + 4) == 0 or bar_index == p1 or p1 == p2 or p2 == p3 or p3 == p4 or bar_index - p4 < mplen
            array.remove(apat, y + 4)
            array.remove(apat, y + 3)
            array.remove(apat, y + 2)
            array.remove(apat, y + 1)
            array.remove(apat, y)
            continue

        xlev = array.get(allpoints, array.get(apat, y + 3))
        minmax = xlev
        mima = array.get(allpoints, array.get(apat, y + 2)) > xlev ? true : false
        start = array.get(apat, y + 3) + 2
        for x = start to array.size(allpoints) > start ? array.size(allpoints) - 1 : na by 2
            if mima and array.get(allpoints, x) > minmax or not mima and array.get(allpoints, x) < minmax
                minmax := array.get(allpoints, x)
                array.set(apat, y + 4, x)
            if mima and array.get(allpoints, x) < xlev or not mima and array.get(allpoints, x) > xlev
                break
    apat
    