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

//@version=5

// @description Show Array or Matrix Elements In Table
library("debug")

// @function Debug Variables in Matrix
// @param _col (int) Assign Column
// @param _row (int) Assign Row
// @param _name (simple matrix) Matrix Name
// @param _value (string) Assign variable as a string (str.tostring())
// @param _lb (string) Constant label (optional)
// @param _ip (int) (default 1) 1 for continuous updates. 2 for barstate.isnew updates. 3 for barstate.isconfirmed updates. -1 to only add once 
// @returns Returns Variable _value output and _msg formatted as '_msg: variableOutput' in designated column and row
export debug(int _col, int _row, simple matrix<string> _name, string _value, string _msg='',  int _ip=1) =>
    ipOn  = _ip == 1 ? true : false
    bsnOn = _ip == 2 ? true : false
    bscOn = _ip == 3 ? true : false
    if matrix.get(_name, _row, _col) == ''
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if ipOn
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bsnOn
        if barstate.isnew
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bscOn
        if barstate.isconfirmed
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))

export debug(int _col, int _row, simple matrix<string> _name, float _value, string _msg='',  int _ip=1) =>
    ipOn  = _ip == 1 ? true : false
    bsnOn = _ip == 2 ? true : false
    bscOn = _ip == 3 ? true : false
    if matrix.get(_name, _row, _col) == ''
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if ipOn
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bsnOn
        if barstate.isnew
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bscOn
        if barstate.isconfirmed
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))

export debug(int _col, int _row, simple matrix<string> _name, int _value, string _msg='',  int _ip=1) =>
    ipOn  = _ip == 1 ? true : false
    bsnOn = _ip == 2 ? true : false
    bscOn = _ip == 3 ? true : false
    if matrix.get(_name, _row, _col) == ''
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if ipOn
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bsnOn
        if barstate.isnew
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bscOn
        if barstate.isconfirmed
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))

export debug(int _col, int _row, simple matrix<string> _name, bool _value, string _msg='',  int _ip=1) =>
    ipOn  = _ip == 1 ? true : false
    bsnOn = _ip == 2 ? true : false
    bscOn = _ip == 3 ? true : false
    if matrix.get(_name, _row, _col) == ''
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if ipOn
        matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bsnOn
        if barstate.isnew
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))
    if bscOn
        if barstate.isconfirmed
            matrix.set(_name, _row, _col, _msg + ": " + str.tostring(_value))


// @function Debug Scope in Matrix - Identify When Scope Is Accessed
// @param _col (int) Column Number
// @param _row (int) Row Number
// @param _name (simple matrix) Matrix Name
// @param _msg (string) Message
// @returns Message appears in debug panel using _col/_row as the identifier
export debugs(int _col, int _row, simple matrix<string> _name, string _msg='') =>
    matrix.set(_name, _row, _col, "debugs(" + str.tostring(_col) + "," + str.tostring(_row) + "): " + _msg)

// Example:
// Define Matrix at beginning of script so functions work throughout the script
// You must add a matrix into the host script as it cannot be imported. 
rows = 2
cols = 1
console = matrix.new<string>(rows,cols,'')

// debug: Show variable value in table                                           
varip ticks = 0.0
ticks := close != close[1] ? ticks + 1 : ticks
if barstate.isconfirmed
    ticks := 0.0
debug(0,0,console,ticks, "debug() This will show up price in table on every bar\nBecause the variable is varip it is counting ticks on every\ncalculation and updating that value on the table.\n(It will update the variable as the value changes on the live bar.)")

// debugs: detect access scopes. Must be placed in scope. 
sampleBool = timenow > time and timenow < time + 60000
if sampleBool
    debugs(0,1,console,"debugs() This will show up in the table for the first 60 seconds\nof a bar sampleBool will have fired this scope.\nIt will not show up in the table thereafter")

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEBUG NOTES:
// Anywhere you want to test the value of a variable, add a debug() function. Debug functions can be stacked together at the end of the script
// However, if you want to clearly see how variables are updated during intrabar calculations, you will need to place the debug function immediately
// below the variable you want to display and see real time updates

// If variable updates are disgused by the execution model, you can place debug() above and below code blocks that modify the variable of interest. 
// This will allow you to see the variable state before and after the processing. If it is in a local scope, you can use debugs() to detect that.
// Historical bars will just use barstate.isconfirmed variables since it will only output the final calculation. 

// Historical states can be viewed using replay mode

// console matrix must be a string matrix. All values in the table will be converted to strings to prevent type errors
// You can use with float, int, and bool types and it will automatically convert the variable to a string

// debug(0,0,rows,"Total Rows")

// Debug-Scope [debugs()] is used to show when a scope is accessed. Thus debugs() must be placed inside the scope being analyzed. 
// if close>open
//     debugs(0,1,"Close>Open")

// debugs:
// CAUTION: Value's will be overwritten if two debug/debugs functions share the same column and row. This can be a desired effect or undesired. 
//          It will generally show the debug() or debugs() function on the lowest line that is assigned to that matrix position.

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// showArray Functions {
// @function Array Element Display (Supports float[], int[], string[], and bool[])
// @param _arrayName ID of Array to be Displayed
// @param _pos Position for Table
// @param _txtSize Size of Table Cell Text
// @param s_index (Optional. Default True.) Show/Hide Index Numbers
// @param s_border (Optional. Default False.) Show/Hide Border
// @param bCol = (Optional. Default Black.) Frame/Border Color.
// @param _fillCond (Optional) Conditional statement. Function displays array only when true. For instances where size is not immediately known or indices are na. Default = true, indicating array size is set at bar_index 0.
// @param _offset (Optional) Use to view historical array states. Default = 0, displaying realtime bar.
// @param _tRows Number of Rows to Display Data In (columns will be calculated accordingly)
// @returns A Display of Array Values in a Table
export viewArray(float[] _arrayName, string _pos, string _txtSize, int _tRows, bool s_index = true, bool s_border = false, string _rowCol = "col", color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        if _rowCol == "col"
            for _i = 0 to endCol
                for _j = 0 to endRow
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endRow
                        row += 1
                row := 0
                if _i < endCol
                    column += 1
        else if _rowCol == "row"
            for _i = 0 to endRow
                for _j = 0 to endCol
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endCol
                        column += 1
                column := 0
                if _i < endRow
                    row += 1

export viewArray(int[] _arrayName, string _pos, string _txtSize, int _tRows, bool s_index = true, bool s_border = false, string _rowCol = "col", color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        if _rowCol == "col"
            for _i = 0 to endCol
                for _j = 0 to endRow
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endRow
                        row += 1
                row := 0
                if _i < endCol
                    column += 1
        else if _rowCol == "row"
            for _i = 0 to endRow
                for _j = 0 to endCol
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endCol
                        column += 1
                column := 0
                if _i < endRow
                    row += 1


export viewArray(string[] _arrayName, string _pos, string _txtSize, int _tRows, bool s_index = true, bool s_border = false, string _rowCol = "col", color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        if _rowCol == "col"
            for _i = 0 to endCol
                for _j = 0 to endRow
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endRow
                        row += 1
                row := 0
                if _i < endCol
                    column += 1
        else if _rowCol == "row"
            for _i = 0 to endRow
                for _j = 0 to endCol
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endCol
                        column += 1
                column := 0
                if _i < endRow
                    row += 1

export viewArray(bool[] _arrayName, string _pos, string _txtSize, int _tRows, bool s_index = true, bool s_border = false, string _rowCol = "col", color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        if _rowCol == "col"
            for _i = 0 to endCol
                for _j = 0 to endRow
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endRow
                        row += 1
                row := 0
                if _i < endCol
                    column += 1
        else if _rowCol == "row"
            for _i = 0 to endRow
                for _j = 0 to endCol
                    table.cell(viewArray, column, row, 
                               text = array.size(_arrayName[_offset]) > index ? 
                                       s_index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : str.tostring(array.get(_arrayName[_offset], index)) : 
                                       "-", 
                               text_halign=text.align_left, 
                               text_valign=text.align_top,
                               text_color=txtCol,
                               text_size=_txtSize)
                    if index <= array.size(_arrayName[_offset]) - 1
                        index += 1
                    if _j < endCol
                        column += 1
                column := 0
                if _i < endRow
                    row += 1
//}

// Examples {
arraySize = 15
a = array.new_float(arraySize, math.round(hlc3,2))
for l = 0 to arraySize - 1
    array.set(a, l, math.round(hlc3[l],2))
viewArray(a, position.top_left, size.normal, 5, true, true, 'col', color.orange, color.purple)

b = array.new_int(arraySize, 0)
inc = 0
for l = 0 to arraySize - 1
    array.set(b, l, inc)
    inc += 1
viewArray(b, position.top_right, size.normal, 5, true, false, 'row')

c = array.new_string(arraySize, "")
str = 'a'
for l = 0 to arraySize - 1
    array.set(c, l, str)
    str := str + 'a'
viewArray(c, position.bottom_left, size.normal, 5, true, false, 'row')
//}

// showMatrix Functions {
// @function Matrix Element Display (Supports <float>, <int>, <string>, and <bool>)
// @param _matrixName ID of Matrix to be Displayed
// @param _pos Position for Table
// @param _txtSize Size of Table Cell Text
// @param s_index (Optional. Default True.) Show/Hide Index Numbers
// @param s_border (Optional. Default False.) Show/Hide Border
// @param bCol = (Optional. Default Black.) Frame/Border Color.
// @param _fillCond (Optional) Conditional statement. Function displays matrix only when true. For instances where size is not immediately known or indices are na. Default = true, indicating matrix size is set at bar_index 0.
// @param _offset (Optional) Use to view historical matrix states. Default = 0, displaying realtime bar.
// @returns A Display of Matrix Values in a Table
export viewMatrix(simple matrix<float> _matrixName, string _pos, string _txtSize, bool s_index = true, bool _resetIdx = true, bool s_border = false, color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row        = 0, column = 0, index = 0
        endCol     = getCols - 1
        endRow     = getRows - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewMatrix, column, row, 
                           text = s_index ? str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row,column)) : str.tostring(matrix.get(_matrixName[_offset],row,column)), 
                           text_halign=text.align_left, 
                           text_valign=text.align_top,
                           text_color=txtCol,
                           text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1
                if _resetIdx
                    index := 0

export viewMatrix(simple matrix<int> _matrixName, string _pos, string _txtSize, bool s_index = true, bool _resetIdx = true, bool s_border = false, color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row        = 0, column = 0, index = 0
        endCol     = getCols - 1
        endRow     = getRows - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewMatrix, column, row, 
                           text = s_index ? str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row,column)) : str.tostring(matrix.get(_matrixName[_offset],row,column)), 
                           text_halign=text.align_left, 
                           text_valign=text.align_top,
                           text_color=txtCol,
                           text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1
                if _resetIdx
                    index := 0

export viewMatrix(simple matrix<string> _matrixName, string _pos, string _txtSize, bool s_index = true, bool _resetIdx = true, bool s_border = false, color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row        = 0, column = 0, index = 0
        endCol     = getCols - 1
        endRow     = getRows - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewMatrix, column, row, 
                           text = s_index ? str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row,column)) : str.tostring(matrix.get(_matrixName[_offset],row,column)), 
                           text_halign=text.align_left, 
                           text_valign=text.align_top,
                           text_color=txtCol,
                           text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1
                if _resetIdx
                    index := 0

export viewMatrix(simple matrix<bool> _matrixName, string _pos, string _txtSize, bool s_index = true, bool _resetIdx = true, bool s_border = false, color bCol = color.black, color txtCol = color.black, bool _fillCond = true, int _offset = 0) =>
    if _fillCond
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows, frame_color=bCol, frame_width=s_border ? 1 : 0, border_color=bCol, border_width=s_border ? 1 : 0)
        row        = 0, column = 0, index = 0
        endCol     = getCols - 1
        endRow     = getRows - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewMatrix, column, row, 
                           text = s_index ? str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row,column)) : str.tostring(matrix.get(_matrixName[_offset],row,column)), 
                           text_halign=text.align_left,
                           text_valign=text.align_top,
                           text_color=txtCol,
                           text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1
                if _resetIdx
                    index := 0
//}

// -- Examples {
d = matrix.new<float>(5, 5, close[1])
viewMatrix(d, position.top_center, size.small, true, true, true)

viewMatrix(console, position.bottom_right, size.normal, false, false, true)
//}