/*

File: calculator_classes.js

SaeSolved::sitewidgets.com(TM) JavaScript Class Library for
Calculators -- Version 1.22, 20020613
Copyright (C) 2002 by SaeSolved::(TM), http://www.sitewidgets.com.

This Library provides a set of classes for use in building calculators.
It handles the basic input and output issues such as formatting and
data validation. Calculator algorithms need to be incorporated in an
instance of the method OperateOnValues() to create a specific calculator.
An example at the end of this library illustrates how this may be done.

This Library is open source software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
(http://www.gnu.org/copyleft/lesser.txt) as published by the Free
Software Foundation; either version 2.1 of the License, or (at your
option) any later version.

In particular you may copy and distribute verbatim copies of the
Library's complete source code as you receive it, in any medium,
provided that you conspicuously and appropriately publish on each
copy an appropriate copyright notice and disclaimer of warranty;
keep intact all the notices that refer to this License and to the
absence of any warranty; and distribute a copy of this License along
with the Library.

This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License (http://www.gnu.org/copyleft/lesser.txt)
for more details.

A copy of the GNU Lesser General Public License may be obtained from
the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307, USA.

It is requested, but not required, that you use the statement in the
variable "this.License" in the function Calculator below in a
document.write statement in such a way as to conspicuously and
appropriately publish on each web page where the calculator is used
the hyperlinked credits, copyright notice, and disclaimer of warranty
contained in the variable "this.License."

SaeSolved::(TM) may be contacted at 1552 Beachview Drive,
Virginia Beach, VA 23464-7225, USA; email: webmaster@saesolved.com.

Version change history:
1.22  20020613 Allow the arguments of SetLayout() to be sent as an array
                Corrected function Validate for blank and zero characters
1.211 20020607 Corrected function Validate for initial non-numeric characters
1.21  20001120 Added method ValidateSubmit().
                Corrected handling of radio element names.
                Added ability to use form and table styles.
1.2   20000822 Added radio and select elements.
1.18  20000817 Added checkbox element, getArgs, font color.
                Element font family, size, and color
                'inherited' from calculator.
1.11  20000214 Fixed Opera-specific bug in SetLayout(), tidied
                ShowRows(), corrected validation for values between
                plus and and minus one.
1.1   20000212 Added SetLayout(), which gives greater flexibilty to
                calculator layout without having to override ShowRows().
                In addition fields can now be specified as input or
                output and fields not having the type 'text' will be
                ignored for both input and output.
1.02  20000209 Check for unwanted commas and extra decimal points,
                provide for footnotes, individual row background colors
1.01  20000201 Allow customizing of background colors
1.00  20000124 Base release
*/

js_version = 1.1;

function Calculator(name, title, helpUsed) {
    this.CalculatorName   = name;
    this.CalculatorTitle  = title;
    if (helpUsed == null){
        this.HelpUsed     = false;
    }else{
        this.HelpUsed     = helpUsed;
    }
    if (this.HelpUsed){
        this.TotalColumns = 2;
    }else{
        this.TotalColumns = 2;
    }
    this.License          = '';
    this.FontFamily       = 'Arial, Helvetica, sans-serif';
    this.FontPoint        = '10 pt';
    this.FontSize         = '1.5';
    this.FontColor        = '#000000';
    this.FormStyle        = null;
    this.TableStyle       = 'border: 1px solid #666666';
    this.TableFormat      = null;
    this.TitleFormatBegin = null;
    this.TitleFormatEnd   = null;
    this.TitleBGColor     = '#CFD6FE';
    this.HelpFormat       = null;
    this.HelpBGColor      = '#E6E6E6';
    this.RowBGColor       = new Array();
    this.DefaultBGColr    = new Array();
    this.DefaultBGColr[0] = '#cccccc';
    this.DefaultBGColr[1] = '#ffffff';
    this.RowFormat        = new Array();
    this.RowFormatEnd     = new Array();
    this.LabelAlign       = 'left';
    this.ValueAlign       = 'left';
    this.LicenseFormatted = null;
    this.index            = 0;
    this.rowindex         = -1;
    this.Element          = new Object();
    this.Calculate        = Calculate;
    this.ValidateSubmit   = ValidateSubmit;
    this.AddElement       = AddElement;
    this.SetLayout        = SetLayout;
    this.SetStyles        = SetStyles;
    this.ShowRows         = ShowRows;
    this.ShowCalculator   = ShowCalculator;
    this.GetValues        = GetValues;
    this.PutValues        = PutValues;
}

function AddElement(obj, indx){
    var ndx = indx;
    if (ndx == null)
        ndx = this.index;
    obj.RowLocn = ndx;
    if (obj.type == 'radio') {
        obj.name = obj.family_name + '_' + ndx;
    }
    this[obj.name] = obj;
    if(obj.BGColor == null)
        obj.BGColor = this.DefaultBGColr[ndx % 2];
    if (this.RowBGColor[ndx] == null)
        this.RowBGColor[ndx] = obj.BGColor;
    if (obj.FontFamily == null)
        obj.FontFamily = this.FontFamily;
    if (obj.FontSize == null)
        obj.FontSize = this.FontSize;
    if (obj.FontColor == null)
        obj.FontColor = this.FontColor;
    if (obj.LabelAlign == null)
        obj.LabelAlign = this.LabelAlign;
    if (obj.ValueAlign == null)
        obj.ValueAlign = this.ValueAlign;
    this.Element[this.index++] = obj;
}

function SetLayout(){
    var args    = new Array();
    if (navigator.userAgent.indexOf('Opera') == -1){
        args    = arguments;
    }else{
        args    = SetLayout.arguments;
        // hack for Opera -- this seems to be required, but the rationale eludes me...
        if (this.rowindex < 0) this.rowindex = 0;
    };
    // allow the arguments to be sent as an array
    if (args.length == 1 && args[0].length != null && args[0].length > 0) args = args[0];
    for (var i = 0; i < args.length; i++){
        var temp = new String(args[i]);
        if (temp.charAt(0) == "#"){
            this.rowindex++;
            if (temp.length > 1){
                this.RowBGColor[this.rowindex] = args[i];
            }else{
                this.RowBGColor[this.rowindex] = this.DefaultBGColr[this.rowindex % 2];
            }
        }else{
            this.AddElement(args[i], this.rowindex);
        }
    }
}

function SetStyles(){
    // This uses defaults for each of the variables unless they have
    // been given explicit values after an object is instantiated
    if(this.FormStyle == null) {
        this.FormStyle = '';
    } else {
        this.FormStyle = ' style="' + this.FormStyle + '"';
    }
    if(this.TableStyle == null) {
        this.TableStyle = '';
    } else {
        this.TableStyle = ' style="' + this.TableStyle + '"';
    }
    if(this.TableFormat == null) this.TableFormat =
        '<span><table width="170" border="0" ' +
        'cellspacing="2" cellpadding="3" align="left" ' +
        'bgcolor="#FFFFFF"' + this.TableStyle + '>';
    if(this.TitleFormatBegin == null) this.TitleFormatBegin =
        '<tr bgcolor="' + this.TitleBGColor + '" style="font-size: ' +
        this.FontPoint + ';  font-family: ' + this.FontFamily +
        '; color: ' + this.FontColor + '; font-style: normal; ' +
        'font-weight: normal; background-color: ' + this.TitleBGColor +
        '"><th colspan="' + this.TotalColumns + '">' +
        '<font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="3">';
    if(this.TitleFormatEnd == null) this.TitleFormatEnd =
        '</font></td></tr>';
    if (this.rowindex < 0 ) this.rowindex = this.index;
    for (var RowNr = 0; RowNr < this.rowindex; RowNr++){
       if(this.RowFormat[RowNr] == null)
            this.RowFormat[RowNr] =
            this.RowFormat[RowNr] =
                '<tr bgcolor="' + this.RowBGColor[RowNr] +
                '" style="font-size: ' + this.FontPoint +
                '; font-family: ' + this.FontFamily +
                '; color: ' + this.FontColor +
                '; font-style: normal' +
                '; font-weight: normal' +
                '; background-color: ' + this.RowBGColor[RowNr] +
                ';">\n';
        if(this.RowFormatEnd[RowNr] == null)
            this.RowFormatEnd[RowNr] = '</tr>';
    }
    if(this.HelpFormat == null) this.HelpFormat =
        'bgcolor="' + this.HelpBGColor + '" style="font-size: ' +
        this.FontPoint + '; font-family: ' + this.FontFamily +
        '; color: ' + this.FontColor + '; font-style: normal; ' +
        'font-weight: normal; background-color: ' +
        this.HelpBGColor + ';';
    if(this.LicenseFormatted == null) this.LicenseFormatted =
        '<tr bgcolor="' + this.TitleBGColor + '" style="font-size: ' +
        '8 pt; font-family: ' + this.FontFamily + '; color: ' +
        this.FontColor + '; font-style: normal; font-weight: ' +
        'normal; background-color: ' + this.TitleBGColor + ';">' +
        '<td colspan="' + this.TotalColumns + '"><font face="' +
        this.FontFamily + '" size="1" color="' + this.FontColor + '">' + this.License +
        '</font></td></tr>\n';
}

function Calculate() {
    var obj = self.document[this.CalculatorName];
    this.GetValues(obj);
    // function OperateOnValues must be supplied in the implementation
    this.OperateOnValues();
    this.PutValues(obj);
}

function ValidateSubmit() {
    var obj = self.document[this.CalculatorName];
    this.GetValues(obj);
    // function ValidateValues must be supplied in the implementation
    if (this.ValidateValues()) {
        obj.submit();
    }
}

function ShowCalculator() {
    this.SetStyles();
    document.write('<form name="' + this.CalculatorName + '" id="' +
        this.CalculatorName + '" target="_self" action="' +
        window.location + '" method="get"' + this.FormStyle + '>\n');
    document.write(this.TableFormat,'\n');
    /*document.write(this.TitleFormatBegin,'\n',this.CalculatorTitle,
        '\n', this.TitleFormatEnd,'\n');*/
    this.ShowRows();
    document.write(this.LicenseFormatted, '</table></span>\n</form>');
}

function ShowRows(){
    var i = 0;
    for (var RowNr = 0; RowNr < this.rowindex; RowNr++){
        document.write(this.RowFormat[RowNr]);
        for (i; i < this.index; i++){
            if (this.Element[i].RowLocn != RowNr) break;
            this.Element[i].ShowElement(this.HelpUsed,
                                        this.TotalColumns);
            
        }
        document.write('   ' + this.RowFormatEnd[RowNr] + '\n');
    }
}

function GetValues(obj){
    for (var i = 0; i < this.index; i++){
        if (this.Element[i].in_out.indexOf('input') != -1 || this.Element[i].in_out == ''){
            if (this.Element[i].type == 'text'){
                var numFieldVal = obj[this.Element[i].value_name].value;
                //get rid of leading and trailing spaces.
                while (numFieldVal.charAt(0) == ' '){
                    numFieldVal = numFieldVal.substring(1)
                }
                while (numFieldVal.charAt(numFieldVal.length - 1) == ' '){
                    numFieldVal = numFieldVal.substring(0, numFieldVal.length - 1)
                }
                if (numFieldVal == null || numFieldVal.length == 0){
                    //assume empty or blank fields are zero
                    this.Element[i].value = 0.0;
                }else{
                    //strip out any commas
                    this.Element[i].value =
                        parseFloat(numFieldVal.toString().split(',').join(''));
                }
            }else if (this.Element[i].type == 'checkbox'){
                var checkboxVal = '';
                if(obj[this.Element[i].value_name].checked == true){
                    checkboxVal = obj[this.Element[i].value_name].value;
                }
                if (this.Element[i].decimals == null) {
                    this.Element[i].value = checkboxVal;
                }else{
                    if (checkboxVal == '') {
                        checkboxVal = '0';
                    }
                    if (this.Element[i].decimals == 0) {
                        this.Element[i].value = parseInt(checkboxVal);
                    }else{
                        this.Element[i].value = parseFloat(checkboxVal);
                    }
                }
            }else if (this.Element[i].type == 'radio_parent'){
                var radioVal = '';
                var radioNam = new Array();
                radioNam = obj[this.Element[i].value_name];
                for (var j = 0; j < radioNam.length; j++){
                    if(radioNam[j].checked == true){
                        radioVal = radioNam[j].value;
                    }
                }
                if (this.Element[i].decimals == null) {
                    this.Element[i].value = radioVal;
                }else{
                    if (radioVal == '') {
                        radioVal = '0';
                    }
                    if (this.Element[i].decimals == 0) {
                        this.Element[i].value = parseInt(radioVal);
                    }else{
                        this.Element[i].value = parseFloat(radioVal);
                    }
                }
            }else if (this.Element[i].type == 'select'){
                this.Element[i].value = this.Element[i].options[obj[this.Element[i].value_name].selectedIndex][0];
            }
        }
    }
}

function PutValues(obj){
    for (var i = 0; i < this.index; i++){
        if (this.Element[i].in_out == 'output' || this.Element[i].in_out == ''){
            if (this.Element[i].type == 'text'){
                obj[this.Element[i].value_name].value = this.Element[i].ShowDecimals();
            }else if (this.Element[i].type == 'checkbox'){
                if(this.Element[i].value == obj[this.Element[i].value_name].value){
                    obj[this.Element[i].value_name].checked = true;
                }else{
                    obj[this.Element[i].value_name].checked = false;
                }
            }else if (this.Element[i].type == 'radio_parent'){
                var radioNam = new Array();
                radioNam = obj[this.Element[i].value_name];
                for (var j = 0; j < radioNam.length; j++){
                    if(this.Element[i].value == radioNam[j].value){
                        radioNam[j].checked = true;
                    }else{
                        radioNam[j].checked = false;
                    }
                }
            }else if (this.Element[i].type == 'select'){
                for (var j = 0; j < this.options.length; j++){
                    if (this.Element[i].value == this.options[j][0]){
                        obj[this.Element[i].value_name].selectedIndex = j;
                    }
                }
            }
        }
    }
}

function CalculatorElement(type, name, label, in_out){
    this.type = type;
    if (this.type == 'radio') {
        this.family_name = name;
    } else {
        this.name        = name;
    }
    this.value_name  = name + '_value';
    this.help_name   = name + '_help';
    if (label == null){
        this.label = '';
    }else{
        this.label = label;
    }
    this.alert_label = this.label.replace(/<[^>]+>/g, '');
    if (in_out == null){
        this.in_out = '';
    }else{
        this.in_out = in_out;
    }
    this.value             = '';
    this.decimals          = null;
    this.size              = 5;
    this.checked           = false;
    this.options           = new Array();
    this.help              = '';
    this.max_value         = null;
    this.min_value         = null;
    this.isHeader          = false;
    this.ColSpan           = null;
    this.RowLocn           = 0;
    this.BGColor           = null;
    this.FontFamily        = null;
    this.FontSize          = null;
    this.FontColor         = null;
    this.LabelAlign        = null;
    this.LabelFormatBegin  = null;
    this.LabelFormatMid    = null;
    this.LabelFormatEnd    = null;
    this.ValuePrefix       = '';
    this.ValuePostfix      = '';
    this.ValueFormatBegin  = null;
    this.ValueFormatMid    = null;
    this.ValueFormatEnd    = null;
    this.HelpFormatBegin   = null;
    this.HelpFormatEnd     = null;
    this.NoteFormatBegin   = null;
    this.NoteFormatMid     = null;
    this.NoteFormatEnd     = null;
    this.ButtonFormatBegin = null;
    this.ButtonFormatMid   = null;
    this.ButtonFormatEnd   = null;
    this.SetFormats        = SetFormats;
    this.ShowElement       = ShowElement;
    this.ShowDecimals      = ShowDecimals;
    this.Validate          = Validate;
    this.HelpScreen        = HelpScreen;
}

function SetFormats(){
    // This uses defaults for each of the variables unless they have
    // been given explicit values after an object is instantiated
    if(this.LabelFormatBegin == null){
        if(this.isHeader){
            this.LabelFormatBegin = '<th';
        }else{
            this.LabelFormatBegin = '<td align="' + this.LabelAlign + '"';
        }
    }
    if(this.LabelFormatMid == null) this.LabelFormatMid =
        '><font face="' + this.FontFamily +
        '" size="' + this.FontSize + '" color="' + this.FontColor + '">';
    if(this.LabelFormatEnd == null){
        this.LabelFormatEnd = '</font>';
        if(this.isHeader){
            this.LabelFormatEnd += '</th>';
        }else{
            this.LabelFormatEnd += '</td>';
        }
    }
    if(this.ValueFormatBegin == null) this.ValueFormatBegin =
        '<td nowrap align="' + this.ValueAlign + '" valign="top"';
    if(this.ValueFormatMid == null) this.ValueFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="' +
        this.FontSize + '">' + this.ValuePrefix;
    if(this.ValueFormatEnd == null) this.ValueFormatEnd =
        this.ValuePostfix + '</font>';
    if(this.HelpFormatBegin == null) this.HelpFormatBegin =
        '<font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="1">';
    if(this.HelpFormatEnd == null) this.HelpFormatEnd =
        '</font></td>';
    if(this.NoteFormatBegin == null) this.NoteFormatBegin =
        '<td align="left"';
    if(this.NoteFormatMid == null) this.NoteFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="1">';
    if(this.NoteFormatEnd == null) this.NoteFormatEnd =
        '</font></td>';
    if(this.ButtonFormatBegin == null) this.ButtonFormatBegin =
        '<td align="center"';
    if(this.ButtonFormatMid == null) this.ButtonFormatMid =
        '><font face="' + this.FontFamily + '" color="' + this.FontColor + '" size="' +
        this.FontSize + '">';
    if(this.ButtonFormatEnd == null) this.ButtonFormatEnd =
        '</font></td>';
}

function ShowElement(withHelp, TotalColumns){
    this.SetFormats();
    var ValueColumns = 1;
    if (       this.type == 'text'
            || this.type == 'checkbox'
            || this.type == 'radio'
            || this.type == 'select'
            || this.type == 'string'){
        if (this.label == ''){
            ValueColumns++;
        }else{
            document.write(
'       ' + this.LabelFormatBegin);
            if (this.ColSpan != null){
                document.write(' colspan="', this.ColSpan, '"');
            }
            document.write(this.LabelFormatMid + '\n',
'           ', this.label, '\n',
'       ' + this.LabelFormatEnd + '\n');
        }
        document.write(
'       ' + this.ValueFormatBegin)
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (ValueColumns > 1){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.ValueFormatMid + '\n');
        if (this.type == 'checkbox'){
            document.write('           <input type="checkbox' +
                '" name="'    + this.value_name + '"');
            if (this.checked){
                document.write(' checked');
            }
            document.write(' value="' + this.value);
        }else if (this.type == 'radio'){
            document.write('           <input type="radio' +
                '" name="'    + this.value_name + '"');
            if (this.checked){
                document.write(' checked');
            }
            document.write(' value="' + this.value);
        }else if (this.type == 'select'){
            document.write('<select ' +
                'name="'    + this.value_name);
        }else{
            document.write('           <input type="text' +
                '" name="'  + this.value_name +
                '" size="'  + this.size  +
                '" value="' + this.value);
            if (this.type == 'text'){
                document.write('" onChange="' + this.name +
                            '.Validate(this);');
            }
        }
        if (this.in_out == 'output'){
            document.write('" readonly');
        }else{
            document.write('"');
        }
        if (this.type == 'select'){
            document.write('>');
            for (var i = 0; i < this.options.length; i++){
                document.write('<option value="', this.options[i][0], '"');
                if (this.value == this.options[i][0]){
                    document.write(' selected');
                }
                document.write('>', this.options[i][1], '</option>');
            }
            document.write('</select');
        }
        document.write('>', this.ValueFormatEnd, this.HelpFormatBegin);
        if (withHelp){
            if (this.help != null && this.help.length > 0){
                document.write('<input type="button' +
                    '" name="'     + this.help_name +
                    '" value=" ? ' +
                    '" onClick="' + this.name + '.HelpScreen();">\n');
            }else{
                document.write(' \n');
            }
        }
        document.write(
'       ' + this.HelpFormatEnd + '\n');
    }else if (this.type == 'label_only' || (this.type == 'radio_parent' && this.label != '')){
        document.write(
'           ' + this.LabelFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }
        document.write(this.LabelFormatMid + '\n',
'               '   + this.label + '\n',
'           ' + this.LabelFormatEnd + '\n');
    }else if (this.type == 'note'){
        document.write(
'           ' + this.NoteFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (TotalColumns > 0){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.NoteFormatMid + '\n',
'               '   + this.label + '\n',
'           ' + this.NoteFormatEnd + '\n');
    }else{
        document.write(
'           ' + this.ButtonFormatBegin);
        if (this.ColSpan != null){
            document.write(' colspan="', this.ColSpan, '"');
        }else if (TotalColumns > 0){
            document.write(' colspan="', TotalColumns, '"');
        }
        document.write(this.ButtonFormatMid + '\n',
'               <input type="button' +
                    '" name="'    + this.value_name  +
                    '" value="'   + this.label +
                    '" onClick="' + this.type +
                    '">\n',
'           ' + this.ButtonFormatEnd + '\n');
    }
}

function HelpScreen(){
    alert(this.help);
    return true;
}

function ShowDecimals(){
    if (this.decimals == null
        || parseFloat(this.value).toString().length
            < this.value.toString().length)
            return this.value;
    var factr = 1;
    for (var i = 0; i < this.decimals; i++){
        factr *= 10;
    }
    var outputStr = Math.round(factr * this.value).toString();
    while (outputStr.length - this.decimals < 1){
        outputStr = '0' + outputStr;
    }
    if (this.decimals == 0)
        return outputStr;
    var pos = outputStr.length - this.decimals;
    return outputStr.substring(0, pos) + '.' +
                outputStr.substring(pos);
}

function Validate(obj){
    if (this.in_out == 'output'){
        alert('"' + this.alert_label + '" is an output value.');
        obj.value = '';
        return true;
    }
    var val = obj.value;
    //strip out any commas
    var val1 = val.toString().split(',').join('');
    var val2 = val1;
    //remove decimal point(s) -- check if there were too many
    val2 = val1.toString().split('.').join('');
    //get rid of leading signs and zeros
    var val3 = val2;
    if (val3.charAt(0) == '+' || val3.charAt(0) == '-'){
        val3 = val3.substring(1)
    }
    while (val3.charAt(0) == '0'){
        val3 = val3.substring(1)
    }
    if (val1.length - val2.length > 1) {
       alert('The value of "' + this.alert_label
            + '" appears to contain more than one decimal point.');
    } else if (val3.length > 0 && (isNaN(parseInt(val3)) 
                                    || parseInt(val3).toString().length < val3.length)) {
       //check for valid numerical value
       alert('You have entered an invalid value (' + val + ') for "'
                + this.alert_label + '."');
    } else if (this.max_value != null && val > this.max_value){
       alert('The value of "' + this.alert_label
            + '" must not be greater than ' + this.max_value + '.');
    } else if (this.min_value != null && val < this.min_value){
       alert('The value of "' + this.alert_label
            + '" must not be less than ' + this.min_value + '.');
    } else {
        return true;
    }
    obj.focus();
    obj.select();
    return false;
}

function getArgs(){
/*  Based on Example 13-5 in "JavaScript: The Definitive Guide," 3rd ed.,
    by David Flanagan, O'Reilly (1998) p. 245.                            */
    var args = new Object();
    var query = window.location.search.substring(1);
    var pairs = new Array();
    if ((pairs = query.split("&")) == null) pairs = localSplit(query, "&");
    for (var i = 0; i < pairs.length; i++){
        var pos = pairs[i].indexOf('=');
        if (pos == -1) continue;
        var argname = pairs[i].substring(0,pos);
        var value = pairs[i].substring(pos+1);
        args[argname] = unescape(value);
    }
    return args;
}