Indie Dev

Hello Guest!. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, sell your games, upload content, as well as connect with other members through your own private inbox!

Solid understanding to object inspections

DoubleX

Adventurer
Xy$
1.12
This post talks about more advanced concepts and techniques about inspecting objects. You're assumed to have at least:
- Some Javascript coding proficiency(Inexperienced Javascript coders having basic knowledge to the default RMMV codebase and written at least several simple but complete plugins)
- Basic knowledge to object inspections

Object Property Trees
Consider this example:
JavaScript:
var obj_1 = {
    obj_prop_1: {
        obj_prop_1_1: {},
    },
    obj_prop_2: {
        obj_prop_2_1: [],
    },
    obj_prop_3: [[]],
    obj_prop_4: [{}],
    obj_prop_5: [],
    obj_prop_6: {},
};
JavaScript:
console.log(obj_1.toSource());
JavaScript:
({obj_prop_1:{obj_prop_1_1:{}}, obj_prop_2:{obj_prop_2_1:[]}, obj_prop_3:[[]], obj_prop_4:[{}], obj_prop_5:[], obj_prop_6:{}})
The object properties linkages can be displayed this way:
JavaScript:
                                  obj_1
                                    |
     -----------------------------------------------------------
     |            |           |          |          |          |
obj_prop_1   obj_prop_2  obj_prop_3 obj_prop_4 obj_prop_5 obj_prop_6
     |            |           |          |
obj_prop_1_1 obj_prop_2_1    []          {}
If you know what a tree is, It's actually a tree with obj_1 as the root and all objects directly or indirectly linked to it as the leaves. The former is the parent of the latters and the latters are childrens of the former. The latters are siblings of each other and the height of that tree is 1. As it shows all object properties linked to obj_1, It's the Object Properties Tree of obj_1.

Consider another example:
JavaScript:
var obj_1 = {
    obj_prop_1: {
        obj_prop_1_1: {},
    },
    obj_prop_2: {
        obj_prop_2_1: [],
    },
    obj_prop_3: [[]],
    obj_prop_4: [{}],
    obj_prop_5: [],
    obj_prop_6: {},
    obj_prop_7: obj_1,
};
JavaScript:
console.log(obj_1.toSource());
JavaScript:
({obj_prop_1:{obj_prop_1_1:{}}, obj_prop_2:{obj_prop_2_1:[]}, obj_prop_3:[[]], obj_prop_4:[{}], obj_prop_5:[], obj_prop_6:{}, obj_prop_7:(void 0)})
The object property tree of obj_1 is this:
JavaScript:
                                  obj_1
                                    |
     ----------------------------------------------------------------------
     |            |           |          |          |          |          |
obj_prop_1   obj_prop_2  obj_prop_3 obj_prop_4 obj_prop_5 obj_prop_6 obj_prop_7
     |            |           |          |                                |
obj_prop_1_1 obj_prop_2_1    []          {}
Note that the obj_prop_7 part's drawn that way to indicate a cyclic linkage, meaning that what's linked to obj_prop_7 is linked by obj_1.
Also, note that
JavaScript:
 obj_prop_1
     |
obj_prop_1_1
Is both a subtree of the obj_1 object property tree and the object property tree of obj_prop_1.
The indirect link between obj_prop_1_1 and obj_1 are shown as the path from obj_1 to obj_prop_1_1:
JavaScript:
                                  obj_1
                                    |
     --------------------------------
     |
obj_prop_1
     |
obj_prop_1_1
obj_prop_1_1 is a children of obj_prop_1, which is a children of obj_1, so obj_prop_1_1 is a descendant of obj_1 and obj_1 is an ancestor of obj_prop_1_1.
If the linkages of all Arrays to obj_1 are to be shown instead, the result will be this:
JavaScript:
                                  obj_1
                                    |
                  -----------------------------------
                  |           |          |          |
              obj_prop_2  obj_prop_3 obj_prop_4 obj_prop_5
                  |           |
             obj_prop_2_1    []
It combines the path from obj_1 to all Arrays, resulting in a reduced object property tree containing all Arrays.

Tree Reduction Recursions
As the root of an object's inspection tree is that object itself, the reduction always starts from the root.
In general, some specified conditions and labels will be used to determine which linked objects will remain in the reduced object property tree and mark all those picked objects respectively. That check will be used on all objects except the root in the object property tree.
When using that check on one of them, the below questions will be asked:
Q1. Does this object refer to an object that's already linked with it?
If yes, do nothing, otherwise ask Q2 and then Q3.
Q2. Does this object meet those specified conditions?
If yes, a specified label will be added to that object to notify that it'll remain in the reduced object property tree, otherwise do nothing.
Q3. Does this object contain other objects?
If yes, then Q1 will be asked on all those objects contained by that currently queried object, otherwise do nothing.
The reduction starts from asking Q3 on the root and ends with removing all objects not having that specified label and not containing any object having that specified label.
This algorithm is actually a tree recursion that uses DFS.

Tree Reduction Plugins
While simple object property trees can be easily reduced manually, complicated ones often need custom plugins to be reduced. 1 such plugin's DoubleX RMMV Object Properties:
Implementations -
JavaScript:
// cond: The function checking whether an object property will be traced
// label: The function returning the label of an traced object property
Object.prototype.trace_obj_prop = function(cond, label) { // New
    if (this._obj_prop_trace === undefined) {
        this._obj_prop_log = {};
        this._obj_prop_trace = {};
    }
    // Stop tracing the object property if the path would be cyclic
    if (this._obj_prop_trace[cond] !== undefined) {
        return;
    }
    //
    this._obj_prop_log[cond] = "";
    this._obj_prop_trace[cond] = {};
    this.log_obj_prop(cond, label);
}; // Object.prototype.trace_obj_prop

// cond: The function checking whether an object property will be traced
// label: The function returning the label of an traced object property
Object.prototype.log_obj_prop = function(cond, label) { // New
    // Checks if the currently traced object property has object properties
    var has_obj_prop = false;
    for (prop in this) {
        if (this.hasOwnProperty(prop) && this.is_obj_prop(prop)) {
            has_obj_prop = true;
            break;
        }
    }
    //
    if (has_obj_prop) {
        this._obj_prop_log[cond] = "{";
        this.traverse_obj_prop_tree(cond, label);
        this._obj_prop_log[cond] += "}";
    }
}; // Object.prototype.log_obj_prop

//----------------------------------------------------------------------------//
// Label and use all nonempty subtrees to form the object property tree       //
//----------------------------------------------------------------------------//
// cond: The function checking whether an object property will be traced
// label: The function returning the label of an traced object property
Object.prototype.traverse_obj_prop_tree = function(cond, label) { // New
    var ot = DoubleX_RMMV.Obj_Prop;
    for (prop in this) {
        if (this.hasOwnProperty(prop) && this.is_obj_prop(prop)) {
            // Recursively traverse the property tree via Depth First Search
            var obj = this[prop];
            if (ot[cond](obj)) {
                this._obj_prop_log[cond] += " " + prop + ": " +
                                            ot[label](obj) + " ";
                this._obj_prop_trace[cond][obj] = [prop];
            }
            var temp_prop = prop;
            obj.trace_obj_prop(cond, label);
            if (Object.keys(obj._obj_prop_trace[cond]).length > 0) {
                if (this._obj_prop_trace[cond][obj] === undefined) {
                    this._obj_prop_trace[cond][obj] = [];
                }
                this._obj_prop_log[cond] += " " + temp_prop + ": " +
                                            obj._obj_prop_log[cond];
                this._obj_prop_trace[cond][obj].push(obj._obj_prop_trace[cond]);
            }
            //
        }
    }
}; // Object.prototype.traverse_obj_prop_tree

// prop: The current object property to be traced
Object.prototype.is_obj_prop = function(prop) { // New
    // Return false for all object properties added by this plugin
    if (prop === "_obj_prop_log" || prop === "_obj_prop_trace") {
        return false;
    }
    if (prop === "trace_obj_prop" || prop === "log_obj_prop") {
        return false;
    }
    return prop !== "traverse_obj_prop_tree" && prop !== "is_obj_prop";
    //
}; // Object.prototype.is_obj_prop

That's all for now. I hope this can help you grasp these more advanced stuffs. For those comprehending object inspections, feel free to correct me if there's anything wrong.
 

eivl

Local Hero
Xy$
0.00
This will be quite helpfull if anyone want to manipulate data. I engurage everyone to make a tree and then sort it, it is a nice exersice :)
 
Top