[LIB] Array / Matrix Display
// 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("ArrayMatrixHUD")

// [-- PINESCRIPT DEBUGGER --] {
// -- Example Define Matrix
rows = 30
cols = 9
varip console = matrix.new<string>(rows,cols,'')

// @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))

// @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) + "): Fired" + _msg)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEBUG NOTE:
// 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
// debug(0,0,rows,"Total Rows")

// DebugScope 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")
    
// 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. 
//          Keep that in mind. 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//}

// [-- 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 _fillCond (Optional) Conditional statement. Function displays array only when true. For instances where 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 _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewArray, column, row, array.size(_arrayName[_offset]) > index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : "-", text_halign=text.align_left, text_size=_txtSize)
                if index <= array.size(_arrayName[_offset]) - 1
                    index += 1
                if _j < endRow
                    row += 1
            row := 0
            if _i < endCol
                column += 1

export viewArray(int[] _arrayName, string _pos, string _txtSize, int _tRows, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewArray, column, row, array.size(_arrayName[_offset]) > index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : "-", text_halign=text.align_left, text_size=_txtSize)
                if index <= array.size(_arrayName[_offset]) - 1
                    index += 1
                if _j < endRow
                    row += 1
            row := 0
            if _i < endCol
                column += 1

export viewArray(string[] _arrayName, string _pos, string _txtSize, int _tRows, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewArray, column, row, array.size(_arrayName[_offset]) > index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : "-", text_halign=text.align_left, text_size=_txtSize)
                if index <= array.size(_arrayName[_offset]) - 1
                    index += 1
                if _j < endRow
                    row += 1
            row := 0
            if _i < endCol
                column += 1

export viewArray(bool[] _arrayName, string _pos, string _txtSize, int _tRows, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getSize   = array.size(_arrayName[_offset])
        getCols   = math.ceil(getSize / _tRows)
        viewArray = table.new(_pos, getCols, _tRows)
        row       = 0, column = 0, index = 0 
        endCol    = getCols - 1
        endRow    = _tRows  - 1
        for _i = 0 to endCol
            for _j = 0 to endRow
                table.cell(viewArray, column, row, array.size(_arrayName[_offset]) > index ? str.tostring(index) + ' - ' + str.tostring(array.get(_arrayName[_offset], index)) : "-", text_halign=text.align_left, text_size=_txtSize)
                if index <= array.size(_arrayName[_offset]) - 1
                    index += 1
                if _j < endRow
                    row += 1
            row := 0
            if _i < endCol
                column += 1

// Examples {
arraySize = 28
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, _offset = 5)

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, open > close, 5)

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, 0)
//} [/endExample]
//}

// [-- 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 _fillCond (Optional) Conditional statement. Function displays matrix only when true. For instances where 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 _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows)
        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, str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row, column)), text_halign=text.align_left, text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1

export viewMatrix(simple matrix<int> _matrixName, string _pos, string _txtSize, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows)
        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, str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row, column)), text_halign=text.align_left, text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1

export viewMatrix(simple matrix<string> _matrixName, string _pos, string _txtSize, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows)
        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, str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row, column)), text_halign=text.align_left, text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1

export viewMatrix(simple matrix<bool> _matrixName, string _pos, string _txtSize, bool _fillCond = true, int _offset = 0) =>
    if _fillCond and bar_index > _offset
        getRows    = matrix.rows(_matrixName[_offset])
        getCols    = matrix.columns(_matrixName[_offset])
        viewMatrix = table.new(_pos, getCols, getRows)
        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, str.tostring(index) + " - " + str.tostring(matrix.get(_matrixName[_offset],row, column)), text_halign=text.align_left, text_size=_txtSize)
                if _j < endRow
                    row += 1
                index += 1
            row := 0
            if _i < endCol
                column += 1


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