<commit_before>"use strict";

var changing = bestGlobals.changing;

myOwn.messages=changing(myOwn.messages, {
    loading: "loading",
    Filter : "Filter",
    Delete : "Delete",
});

myOwn.es=changing(myOwn.es, {
    loading: "cargando",
    Filter : "Filtrar",
    Delete : "Eliminar",
});

var escapeRegExp = bestGlobals.escapeRegExp;

myOwn.firstDisplayCount = 20;
myOwn.displayCountBreaks = [100,250,1000];
myOwn.displayCountBreaks = [50,100,500];
myOwn.comparator={
    '=':function(valueToCheck,condition){return valueToCheck == condition;},
    '~':function(valueToCheck,condition){return RegExp(escapeRegExp(condition),'i').test(valueToCheck);},
    '/R/i':function(valueToCheck,condition){return RegExp(condition,'i').test(valueToCheck);},
    '\u2205':function(valueToCheck,condition){return valueToCheck == null;},//\u2205 = conjunto vacío
    '>':function(valueToCheck,condition){return (valueToCheck>condition)},
    '>=':function(valueToCheck,condition){return (valueToCheck>=condition)},
    '<':function(valueToCheck,condition){return (valueToCheck<condition)},
    '<=':function(valueToCheck,condition){return (valueToCheck<=condition)},
    'not-an-operator':function(valueToCheck,condition){ return 'Operator does not exist'}
}
myOwn.tableGrid = function tableGrid(layout, tableName){
    var my = this;
    var inputColspan = 1;
    var modes = {
        saveByField: true
    };
    layout.textContent = my.messages.loading+'...';
    var grid={};
    var createRowElements;
    var createRowFilter;
    var footInfoElement;
    var structureRequest = my.ajax.table.structure({
        table:tableName,
    }).then(function(tableDef){
        grid.def=tableDef;
        var buttonInsert;
        var buttonCreateFilter;
        var buttonDestroyFilter;
        var getSaveModeImgSrc=function(){ return modes.saveByField?'img/tables-update-by-field.png':'img/tables-update-by-row.png';};
        var buttonSaveModeImg=html.img({src:getSaveModeImgSrc()}).create();
        var buttonSaveMode;
        if(tableDef.allow.update){
            buttonSaveMode=html.button({class:'table-button'}, [buttonSaveModeImg]).create();
            buttonSaveMode.addEventListener('click',function(){
                modes.saveByField = !modes.saveByField;
                buttonSaveModeImg.src=getSaveModeImgSrc();
            });
        }
        if(tableDef.allow.insert){
            buttonInsert=html.button({class:'table-button'}, [html.img({src:'img/insert.png'})]).create();
            buttonInsert.addEventListener('click', function(){
                grid.createRowElements(0);
            });
        }
        if(tableDef.allow.filter){
            buttonCreateFilter=html.button({class:'table-button', 'when-filter':'no'}, [html.img({src:'img/filter.png'})]).create();
            buttonCreateFilter.addEventListener('click', function(){
                grid.createRowFilter(0);
            });
            buttonDestroyFilter=html.button({class:'table-button', 'when-filter':'yes'}, [html.img({src:'img/destroy-filter.png'})]).create();
            buttonDestroyFilter.addEventListener('click', function(){
                grid.destroyRowFilter(0);
            });
        }
        var columnsHeadElements = tableDef.fields.map(function(fieldDef){
            return html.th({colspan:inputColspan},fieldDef.title);
        });
        footInfoElement = html.td({colspan:columnsHeadElements.length*inputColspan, "is-processing":"1"}).create();
        [
            {name:'displayFrom', value:'0'},
            {name:'elipsis', value:' ... '},
            {name:'displayTo', value:'?'},
            {name:'rowCount', value:''}
        ].forEach(function(info){
            footInfoElement[info.name] = html.span(info.value).create();
            footInfoElement.appendChild(footInfoElement[info.name]);
        });
        grid.element = html.table({"class":"my-grid", "my-table": tableName},[
            html.caption(tableDef.title),
            html.thead([
                html.tr([html.th([buttonInsert,/*buttonSaveMode,*/buttonCreateFilter,buttonDestroyFilter])].concat(columnsHeadElements))
            ]),
            html.tbody(),
            html.tfoot([
                html.tr([html.th(),footInfoElement])
            ])
        ]).create();
        layout.innerHTML='';
        layout.appendChild(grid.element);
    });
    var displayGrid = function displayGrid(rows){
        var tbody = grid.element.tBodies[0];
        var updateRowData = function updateRowData(tr, updatedRow){
            var forInsert = false; // not define how to detect
            tr.info.row = updatedRow;
            tr.info.status = 'retrieved';
            tr.info.primaryKeyValues = grid.def.primaryKey.map(function(fieldName){
                return tr.info.row[fieldName];
            });
            grid.def.fields.forEach(function(fieldDef){
                var td = tr.info.rowControls[fieldDef.name];
                td.contentEditable=grid.def.allow.update && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
                td.setTypedValue(tr.info.row[fieldDef.name]);
            });
        }
        var saveRow = function(tr, opts){
            var changeIoStatus = function changeIoStatus(newStatus, title){
                fieldNames.forEach(function(name){
                    var td=tr.info.rowControls[name];
                    td.setAttribute('io-status', newStatus);
                    if(title){
                        //td.title=err.message;
                    }
                });
            }
            var fieldNames=Object.keys(tr.info.rowPendingForUpdate);
            changeIoStatus('updating');
            my.ajax.table['save-record']({
                table:tableName,
                primaryKeyValues:tr.info.primaryKeyValues,
                newRow:tr.info.rowPendingForUpdate,
                status:tr.info.status
            },opts).then(function(updatedRow){
                my.adaptData(grid.def,[updatedRow]);
                updateRowData(tr, updatedRow);
                tr.info.rowPendingForUpdate = {};
                changeIoStatus('temporal-ok');
                setTimeout(function(){
                    changeIoStatus('ok');
                },3000);
            }).catch(function(err){
                changeIoStatus('error',err.message);
            });
        }
        grid.createRowElements = function createRowElements(iRow, row){
            var forInsert = iRow>=0;
            var tr = tbody.insertRow(iRow);
            tr.info = {
                rowControls:{},
                row: {},
                rowPendingForUpdate:{},
                primaryKeyValues:false,
                status: 'new'
            };
            var thActions=html.th().create();
            tr.appendChild(thActions);
            var actionNamesList = ['insert','delete'].concat(grid.def.actionNamesList);
            actionNamesList.forEach(function(actionName){
                var actionDef = my.tableAction[actionName];
                if(grid.def.allow[actionName]){
                    var buttonAction=html.button({class:'table-button'}, [
                        html.img({src:actionDef.img})
                    ]).create();
                    thActions.appendChild(buttonAction);
                    buttonAction.addEventListener('click', function(){
                        actionDef.actionRow(my,grid,tr);
                    });
                }
            });
            grid.def.fields.forEach(function(fieldDef){
                var td = html.td({colspan:inputColspan}).create();
                TypedControls.adaptElement(td, fieldDef);
                tr.info.rowControls[fieldDef.name] = td;
                td.contentEditable=grid.def.allow.update && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
                td.addEventListener('update',function(){
                    var value = this.getTypedValue();
                    if(value!==tr.info.row[fieldDef.name]){
                        this.setAttribute('io-status', 'pending');
                        tr.info.rowPendingForUpdate[fieldDef.name] = value;
                        if(modes.saveByField){
                            saveRow(tr,{visiblyLogErrors:false});
                        }
                    }
                });
                tr.appendChild(td);
            });
            tr.addEventListener('focusout', function(event){
                if(event.target.parentNode != (event.relatedTarget||{}).parentNode ){
                    if(Object.keys(tr.info.rowPendingForUpdate).length){
                        saveRow(tr);
                    }
                }
            });
            return tr;
        }
        grid.destroyRowFilter = function destroyRowFilter(){
            var tr=grid.hasFilterRow;
            grid.element.setAttribute('has-filter',0);
            grid.element.tHead.removeChild(tr);
            delete grid.hasFilterRow;
        }
        grid.element.setAttribute('has-filter',0);
        grid.createRowFilter = function createRowFilter(){
            // var tr=html.tr().create();
            if(grid.hasFilterRow){
                return true;
            }
            var buttonFilter=html.button(myOwn.messages.Filter+"!").create();
            var tr=html.tr({'class':'filter-line'}, [html.th([buttonFilter])]).create();
            grid.hasFilterRow=tr;
            grid.element.setAttribute('has-filter',1);
            grid.element.tHead.appendChild(tr);
            // tr.appendChild(html.td().create());
            tr.info = {
                rowControls:{},
                row: {},
                rowSymbols: {},
                isFilterPending:false,
            };
            buttonFilter.addEventListener('click',function(){
                grid.displayBody(tr.info);
            });
            grid.def.fields.forEach(function(fieldDef){
                var fieldName=fieldDef.name;
                tr.info.rowSymbols[fieldName]=fieldDef.typeName==='text'?'~':'=';
                var symbolFilter=html.button({"class":'auto-filter', tabindex:-1},tr.info.rowSymbols[fieldName]).create();
                var elementFilter=html.span({"class":"filter-span"}).create();
                elementFilter.contentEditable=true;
                tr.info.rowControls[fieldName]=elementFilter;
                elementFilter.addEventListener('update',function(){
                    tr.info.row[fieldDef.name]=this.getTypedValue();
                });
                TypedControls.adaptElement(elementFilter,fieldDef);
                tr.appendChild(html.td({"class":"autoFilter"},[symbolFilter,elementFilter]).create());
            });
        }
        grid.displayBody=function displayBody(filterData){
            if(filterData){
                var rowsToDisplay= rows.filter(function(row,i){
                    var partialOk=true;
                    for(var columna in row){
                        if(filterData.row[columna]!=null){
                            var isSatisfied=my.comparator[filterData.rowSymbols[columna]](row[columna],filterData.row[columna])
                            if(!isSatisfied){
                                partialOk=false;
                            }
                        }
                    }
                    return partialOk;
                })
            }else{
                var rowsToDisplay=rows;
            }
            var displayRows = function displayRows(fromRowNumber, toRowNumber, adding){
                if(!adding){
                    tbody.innerHTML='';
                }
                for(var iRow=fromRowNumber; iRow<toRowNumber; iRow++){
                    (function(row){
                        var tr=grid.createRowElements(-1);
                        updateRowData(tr, row);
                    })(rowsToDisplay[iRow]);
                }
                footInfoElement.displayFrom.textContent=rowsToDisplay.length?1:0;
                footInfoElement.displayTo.textContent=iRow;
                footInfoElement.rowCount.innerHTML='';
                if(iRow<rowsToDisplay.length){
                    var addButtonRest = function addButtonRest(toNextRowNumber){
                        var buttonRest=html.button("+..."+toNextRowNumber).create();
                        footInfoElement.rowCount.appendChild(html.span('  ').create());
                        footInfoElement.rowCount.appendChild(buttonRest);
                        buttonRest.addEventListener('click',function(){
                            displayRows(iRow, toNextRowNumber, true);
                        });
                    }
                    my.displayCountBreaks.forEach(function(size, iSize){
                        var cut=(iRow+size) - (iRow+size) % size;
                        if(cut*5<=rowsToDisplay.length*3 && (iSize==my.displayCountBreaks.length-1 || cut*5<=my.displayCountBreaks[iSize+1]*3)){
                            addButtonRest(cut);
                        }
                    });
                    addButtonRest(rowsToDisplay.length);
                }
            }
            displayRows(0, Math.min(my.firstDisplayCount,rowsToDisplay.length));
        }
        grid.displayBody();
    }
    my.ajax.table.data({
        table:tableName
    }).then(function(rows){
        return structureRequest.then(function(){
            my.adaptData(grid.def,rows);
            displayGrid(rows);
            return grid;
        });
    }).catch(function(err){
        my.log(err);
    })
}

myOwn.tableAction={
    "insert":{
        img: 'img/insert.png',
        actionRow: function(my, grid, tr){
            return grid.createRowElements(
                ('sectionRowIndex' in tr?
                    tr.sectionRowIndex:
                    tr.rowIndex-grid.element.tHead.rows.length
                )+1
            )
        }
    },
    "delete":{
        img: 'img/delete.png',
        actionRow: function(my, grid, tr){
            return my.showQuestion(my.messages.Delete+' '+JSON.stringify(tr.info.primaryKeyValues)+' ?').then(function(result){
                if(result){
                    return (tr.info.primaryKeyValues===false?
                        Promise.resolve():
                        my.ajax.table['delete-record']({
                            table:grid.def.name,
                            primaryKeyValues:tr.info.primaryKeyValues
                        })
                    ).then(function(){
                        my.fade(tr);
                    });
                }
            });
        }
    }
}<commit_msg>Ordena las columnas<commit_after>"use strict";

var changing = bestGlobals.changing;

myOwn.messages=changing(myOwn.messages, {
    loading: "loading",
    Filter : "Filter",
    Delete : "Delete",
});

myOwn.es=changing(myOwn.es, {
    loading: "cargando",
    Filter : "Filtrar",
    Delete : "Eliminar",
});

var escapeRegExp = bestGlobals.escapeRegExp;

myOwn.firstDisplayCount = 20;
myOwn.displayCountBreaks = [100,250,1000];
myOwn.displayCountBreaks = [50,100,500];
myOwn.comparator={
    '=':function(valueToCheck,condition){return valueToCheck == condition;},
    '~':function(valueToCheck,condition){return RegExp(escapeRegExp(condition),'i').test(valueToCheck);},
    '/R/i':function(valueToCheck,condition){return RegExp(condition,'i').test(valueToCheck);},
    '\u2205':function(valueToCheck,condition){return valueToCheck == null;},//\u2205 = conjunto vacío
    '>':function(valueToCheck,condition){return (valueToCheck>condition)},
    '>=':function(valueToCheck,condition){return (valueToCheck>=condition)},
    '<':function(valueToCheck,condition){return (valueToCheck<condition)},
    '<=':function(valueToCheck,condition){return (valueToCheck<=condition)},
    'not-an-operator':function(valueToCheck,condition){ return 'Operator does not exist'}
}
myOwn.tableGrid = function tableGrid(layout, tableName){
    var my = this;
    var inputColspan = 1;
    var modes = {
        saveByField: true
    };
    layout.textContent = my.messages.loading+'...';
    var grid={};
    var createRowElements;
    var createRowFilter;
    var footInfoElement;
    var structureRequest = my.ajax.table.structure({
        table:tableName,
    }).then(function(tableDef){
        grid.def=tableDef;
        grid.view={
            sortColumns:tableDef.sortColumns||[]
        }
        var buttonInsert;
        var buttonCreateFilter;
        var buttonDestroyFilter;
        var getSaveModeImgSrc=function(){ return modes.saveByField?'img/tables-update-by-field.png':'img/tables-update-by-row.png';};
        var buttonSaveModeImg=html.img({src:getSaveModeImgSrc()}).create();
        var buttonSaveMode;
        if(tableDef.allow.update){
            buttonSaveMode=html.button({class:'table-button'}, [buttonSaveModeImg]).create();
            buttonSaveMode.addEventListener('click',function(){
                modes.saveByField = !modes.saveByField;
                buttonSaveModeImg.src=getSaveModeImgSrc();
            });
        }
        if(tableDef.allow.insert){
            buttonInsert=html.button({class:'table-button'}, [html.img({src:'img/insert.png'})]).create();
            buttonInsert.addEventListener('click', function(){
                grid.createRowElements(0);
            });
        }
        if(tableDef.allow.filter){
            buttonCreateFilter=html.button({class:'table-button', 'when-filter':'no'}, [html.img({src:'img/filter.png'})]).create();
            buttonCreateFilter.addEventListener('click', function(){
                grid.createRowFilter(0);
            });
            buttonDestroyFilter=html.button({class:'table-button', 'when-filter':'yes'}, [html.img({src:'img/destroy-filter.png'})]).create();
            buttonDestroyFilter.addEventListener('click', function(){
                grid.destroyRowFilter(0);
            });
        }
        var columnsHeadElements = tableDef.fields.map(function(fieldDef){
            var tr=html.th({colspan:inputColspan},fieldDef.title).create();
            tr.addEventListener('click',function(){
                var currentOrder=grid.view.sortColumns.length && grid.view.sortColumns[0].column==fieldDef.name?grid.view.sortColumns[0].order:null;
                grid.view.sortColumns=grid.view.sortColumns.filter(function(sortColumn){
                    return sortColumn.column != fieldDef.name;
                })
                grid.view.sortColumns.unshift({column:fieldDef.name, order:currentOrder?-currentOrder:1})
                grid.displayBody(tr.info)
            });
            return tr;
        });
        footInfoElement = html.td({colspan:columnsHeadElements.length*inputColspan, "is-processing":"1"}).create();
        [
            {name:'displayFrom', value:'0'},
            {name:'elipsis', value:' ... '},
            {name:'displayTo', value:'?'},
            {name:'rowCount', value:''}
        ].forEach(function(info){
            footInfoElement[info.name] = html.span(info.value).create();
            footInfoElement.appendChild(footInfoElement[info.name]);
        });
        grid.element = html.table({"class":"my-grid", "my-table": tableName},[
            html.caption(tableDef.title),
            html.thead([
                html.tr([html.th([buttonInsert,/*buttonSaveMode,*/buttonCreateFilter,buttonDestroyFilter])].concat(columnsHeadElements))
            ]),
            html.tbody(),
            html.tfoot([
                html.tr([html.th(),footInfoElement])
            ])
        ]).create();
        layout.innerHTML='';
        layout.appendChild(grid.element);
    });
    var displayGrid = function displayGrid(rows){
        var tbody = grid.element.tBodies[0];
        var updateRowData = function updateRowData(tr, updatedRow){
            var forInsert = false; // not define how to detect
            tr.info.row = updatedRow;
            tr.info.status = 'retrieved';
            tr.info.primaryKeyValues = grid.def.primaryKey.map(function(fieldName){
                return tr.info.row[fieldName];
            });
            grid.def.fields.forEach(function(fieldDef){
                var td = tr.info.rowControls[fieldDef.name];
                td.contentEditable=grid.def.allow.update && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
                td.setTypedValue(tr.info.row[fieldDef.name]);
            });
        }
        var saveRow = function(tr, opts){
            var changeIoStatus = function changeIoStatus(newStatus, title){
                fieldNames.forEach(function(name){
                    var td=tr.info.rowControls[name];
                    td.setAttribute('io-status', newStatus);
                    if(title){
                        //td.title=err.message;
                    }
                });
            }
            var fieldNames=Object.keys(tr.info.rowPendingForUpdate);
            changeIoStatus('updating');
            my.ajax.table['save-record']({
                table:tableName,
                primaryKeyValues:tr.info.primaryKeyValues,
                newRow:tr.info.rowPendingForUpdate,
                status:tr.info.status
            },opts).then(function(updatedRow){
                my.adaptData(grid.def,[updatedRow]);
                updateRowData(tr, updatedRow);
                tr.info.rowPendingForUpdate = {};
                changeIoStatus('temporal-ok');
                setTimeout(function(){
                    changeIoStatus('ok');
                },3000);
            }).catch(function(err){
                changeIoStatus('error',err.message);
            });
        }
        grid.createRowElements = function createRowElements(iRow, row){
            var forInsert = iRow>=0;
            var tr = tbody.insertRow(iRow);
            tr.info = {
                rowControls:{},
                row: {},
                rowPendingForUpdate:{},
                primaryKeyValues:false,
                status: 'new'
            };
            var thActions=html.th().create();
            tr.appendChild(thActions);
            var actionNamesList = ['insert','delete'].concat(grid.def.actionNamesList);
            actionNamesList.forEach(function(actionName){
                var actionDef = my.tableAction[actionName];
                if(grid.def.allow[actionName]){
                    var buttonAction=html.button({class:'table-button'}, [
                        html.img({src:actionDef.img})
                    ]).create();
                    thActions.appendChild(buttonAction);
                    buttonAction.addEventListener('click', function(){
                        actionDef.actionRow(my,grid,tr);
                    });
                }
            });
            grid.def.fields.forEach(function(fieldDef){
                var td = html.td({colspan:inputColspan}).create();
                TypedControls.adaptElement(td, fieldDef);
                tr.info.rowControls[fieldDef.name] = td;
                td.contentEditable=grid.def.allow.update && (forInsert?fieldDef.allow.insert:fieldDef.allow.update);
                td.addEventListener('update',function(){
                    var value = this.getTypedValue();
                    if(value!==tr.info.row[fieldDef.name]){
                        this.setAttribute('io-status', 'pending');
                        tr.info.rowPendingForUpdate[fieldDef.name] = value;
                        if(modes.saveByField){
                            saveRow(tr,{visiblyLogErrors:false});
                        }
                    }
                });
                tr.appendChild(td);
            });
            tr.addEventListener('focusout', function(event){
                if(event.target.parentNode != (event.relatedTarget||{}).parentNode ){
                    if(Object.keys(tr.info.rowPendingForUpdate).length){
                        saveRow(tr);
                    }
                }
            });
            return tr;
        }
        grid.destroyRowFilter = function destroyRowFilter(){
            var tr=grid.hasFilterRow;
            grid.element.setAttribute('has-filter',0);
            grid.element.tHead.removeChild(tr);
            delete grid.hasFilterRow;
        }
        grid.element.setAttribute('has-filter',0);
        grid.createRowFilter = function createRowFilter(){
            // var tr=html.tr().create();
            if(grid.hasFilterRow){
                return true;
            }
            var buttonFilter=html.button(myOwn.messages.Filter+"!").create();
            var tr=html.tr({'class':'filter-line'}, [html.th([buttonFilter])]).create();
            grid.hasFilterRow=tr;
            grid.element.setAttribute('has-filter',1);
            grid.element.tHead.appendChild(tr);
            // tr.appendChild(html.td().create());
            tr.info = {
                rowControls:{},
                row: {},
                rowSymbols: {},
                isFilterPending:false,
            };
            buttonFilter.addEventListener('click',function(){
                grid.displayBody(tr.info);
            });
            grid.def.fields.forEach(function(fieldDef){
                var fieldName=fieldDef.name;
                tr.info.rowSymbols[fieldName]=fieldDef.typeName==='text'?'~':'=';
                var symbolFilter=html.button({"class":'auto-filter', tabindex:-1},tr.info.rowSymbols[fieldName]).create();
                var elementFilter=html.span({"class":"filter-span"}).create();
                elementFilter.contentEditable=true;
                tr.info.rowControls[fieldName]=elementFilter;
                elementFilter.addEventListener('update',function(){
                    tr.info.row[fieldDef.name]=this.getTypedValue();
                });
                TypedControls.adaptElement(elementFilter,fieldDef);
                tr.appendChild(html.td({"class":"autoFilter"},[symbolFilter,elementFilter]).create());
            });
        }
        grid.displayBody=function displayBody(filterData){
            if(filterData){
                var rowsToDisplay= rows.filter(function(row,i){
                    var partialOk=true;
                    for(var column in row){
                        if(filterData.row[column]!=null){
                            var isSatisfied=my.comparator[filterData.rowSymbols[column]](row[column],filterData.row[column])
                            if(!isSatisfied){
                                partialOk=false;
                            }
                        }
                    }
                    return partialOk;
                })
            }else{
                var rowsToDisplay=rows;
            }
            if(grid.view.sortColumns.length>0){
                rowsToDisplay.sort(function(a,b){
                    var column;
                    var i=0;
                    do{
                        column=grid.view.sortColumns[i].column;
                        if(a[column]>b[column]){
                            return 1*grid.view.sortColumns[i].order;
                        }else if(a[column]<b[column]){
                            return -1*grid.view.sortColumns[i].order;
                        }
                        i++;
                    }while(i<grid.view.sortColumns.length);
                    return 0;
                });
            }
            var displayRows = function displayRows(fromRowNumber, toRowNumber, adding){
                if(!adding){
                    tbody.innerHTML='';
                }
                for(var iRow=fromRowNumber; iRow<toRowNumber; iRow++){
                    (function(row){
                        var tr=grid.createRowElements(-1);
                        updateRowData(tr, row);
                    })(rowsToDisplay[iRow]);
                }
                footInfoElement.displayFrom.textContent=rowsToDisplay.length?1:0;
                footInfoElement.displayTo.textContent=iRow;
                footInfoElement.rowCount.innerHTML='';
                if(iRow<rowsToDisplay.length){
                    var addButtonRest = function addButtonRest(toNextRowNumber){
                        var buttonRest=html.button("+..."+toNextRowNumber).create();
                        footInfoElement.rowCount.appendChild(html.span('  ').create());
                        footInfoElement.rowCount.appendChild(buttonRest);
                        buttonRest.addEventListener('click',function(){
                            displayRows(iRow, toNextRowNumber, true);
                        });
                    }
                    my.displayCountBreaks.forEach(function(size, iSize){
                        var cut=(iRow+size) - (iRow+size) % size;
                        if(cut*5<=rowsToDisplay.length*3 && (iSize==my.displayCountBreaks.length-1 || cut*5<=my.displayCountBreaks[iSize+1]*3)){
                            addButtonRest(cut);
                        }
                    });
                    addButtonRest(rowsToDisplay.length);
                }
            }
            displayRows(0, Math.min(my.firstDisplayCount,rowsToDisplay.length));
        }
        grid.displayBody();
    }
    my.ajax.table.data({
        table:tableName
    }).then(function(rows){
        return structureRequest.then(function(){
            my.adaptData(grid.def,rows);
            displayGrid(rows);
            return grid;
        });
    }).catch(function(err){
        my.log(err);
    })
}

myOwn.tableAction={
    "insert":{
        img: 'img/insert.png',
        actionRow: function(my, grid, tr){
            return grid.createRowElements(
                ('sectionRowIndex' in tr?
                    tr.sectionRowIndex:
                    tr.rowIndex-grid.element.tHead.rows.length
                )+1
            )
        }
    },
    "delete":{
        img: 'img/delete.png',
        actionRow: function(my, grid, tr){
            return my.showQuestion(my.messages.Delete+' '+JSON.stringify(tr.info.primaryKeyValues)+' ?').then(function(result){
                if(result){
                    return (tr.info.primaryKeyValues===false?
                        Promise.resolve():
                        my.ajax.table['delete-record']({
                            table:grid.def.name,
                            primaryKeyValues:tr.info.primaryKeyValues
                        })
                    ).then(function(){
                        my.fade(tr);
                    });
                }
            });
        }
    }
}<|endoftext|>


<commit_before>const express = require('express');
const app = express();
const db = require('./models');
const baseSpells = db.base_spells;

// app.use(bp.urlencoded({extended : true}));

app.get('/', (req,res)=>{
  baseSpells.findAll()
  .then((data =>{
    console.log('data: ', data);

    let allSpells = { base_spells: { } };

    data.forEach((dataSet) =>{

      let outerKeyWordObj = {};
      allSpells.base_spells[dataSet.dataValues.key_word] = {
        word: dataSet.dataValues.word,
        prompt: dataSet.dataValues.prompt,
        hint: dataSet.dataValues.hint,
      };;
      console.log('allSpells: ', allSpells);

    });

    res.json({
      sucess: true,
      allSpells,
    });
  }));
});

app.listen(3000, function() {
  console.log('server started');
  db.sequelize.sync();
});
module.exports = app;
<commit_msg>remove litter<commit_after>const express = require('express');
const app = express();
const db = require('./models');
const baseSpells = db.base_spells;

app.get('/', (req,res)=>{
  baseSpells.findAll()
  .then((data =>{
    let allSpells = { base_spells: { } };

    data.forEach((dataSet) =>{

      let outerKeyWordObj = {};
      allSpells.base_spells[dataSet.dataValues.key_word] = {
        word: dataSet.dataValues.word,
        prompt: dataSet.dataValues.prompt,
        hint: dataSet.dataValues.hint,
      };
    });

    res.json({
      sucess: true,
      allSpells,
    });
  }));
});

app.listen(3000, function() {
  console.log('server started');
  db.sequelize.sync();
});
module.exports = app;
<|endoftext|>


<commit_before>/*
 * File   : <CVS Filename>
 * Date   : <CVS Checkout Date>
 * Version: <CVS Version>
 *
 * Copyright (C) 2000  The OpenCms Group
 *
 * This File is part of OpenCms -
 * the Open Source Content Mananagement System
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * For further information about OpenCms, please see the
 * OpenCms Website: http://www.opencms.com
 *
 * You should have received a copy of the GNU General Public License
 * long with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//------------------------------------------------------//
// Script for editcontrol
//------------------------------------------------------//

// Definition of Constants
var CLOSE=1;
var SAVECLOSE=2;
var SAVE=3;

var UNDO=4;
var REDO=5;

var SEARCH=6;
var REPLACE=7;
var GOTO=8;

var CUT=9;
var COPY=10;
var PASTE=11;

var IMPORT=12;
var EXPORT=13;
var EXPORTAS=14;

var PRINT=15;

var windowWidth=null;
var windowHeight=null;
var NS = null;
var IE = null;
var str=null;
var textSetted=null;

NS = (document.layers)? true:false;
IE = (document.all)? true:false;

function getDimensions() {
	if( NS==true ) {
		windowWidth = innerWidth-20;
		windowHeight = innerHeight-20;
	}
	else if( IE==true ) {
		windowWidth = document.body.clientWidth-20;
		windowHeight = document.body.clientHeight-20;
	}
}

// to load the file content into the editor
function setText()
{
	  if(! textSetted )
	  {
		 if (IE)
	   		document.all.edit1.Text = unescape("<#=content#>");
		 else if (NS)
			document.EDITTEXT.TextEditor.value = unescape(code);
	   	textSetted = true;
	}
}

// Function action on button click
function doEdit(para)
{
	switch(para)
	{
	case 1:
	{
		top.close();
		break;
	}
	case 2:
	{
		history.back();
		break;
	}
	case 3:
	{
		//	history.back();
			break;
	}

	case 4:
	{
		document.all.edit1.Undo();
		break;
	}
	case 5:
	{
		document.all.edit1.Redo();
		break;
	}
	case 6:
	{
		document.all.edit1.ShowFindDialog();
		break;
	}
	case 7:
	{
		document.all.edit1.ShowReplaceDialog();
		break;
	}
	case 8:
	{
		document.all.edit1.ShowGotoLineDialog();
		break;
	}
	case 9:
	{
		document.all.edit1.CutToClipboard();
		break;
	}
	case 10:
	{
		document.all.edit1.CopyToClipboard();
		break;
	}
	case 11:
	{
		document.all.edit1.PasteFromClipboard();
		break;
	}
	case 12:
	{
	    document.all.edit1.OpenFile();
		break;
	}
	case 13:
	{
	    document.all.edit1.SaveFile();
		break;
	}
	case 14:
	{
	    document.all.edit1.SaveFileAs();
		break;
	}
	case 15:
	{
	    document.all.edit1.PrintText();
		break;
	}
	default:
	{
		alert("NYI");
		break;
	}
}
	document.all.edit1.focus();
}<commit_msg>Texteditor für NS (Skript)<commit_after>/*
 * File   : <CVS Filename>
 * Date   : <CVS Checkout Date>
 * Version: <CVS Version>
 *
 * Copyright (C) 2000  The OpenCms Group
 *
 * This File is part of OpenCms -
 * the Open Source Content Mananagement System
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * For further information about OpenCms, please see the
 * OpenCms Website: http://www.opencms.com
 *
 * You should have received a copy of the GNU General Public License
 * long with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//------------------------------------------------------//
// Script for editcontrol
//------------------------------------------------------//

// Definition of Constants
var CLOSE=1;
var SAVECLOSE=2;
var SAVE=3;

var UNDO=4;
var REDO=5;

var SEARCH=6;
var REPLACE=7;
var GOTO=8;

var CUT=9;
var COPY=10;
var PASTE=11;

var IMPORT=12;
var EXPORT=13;
var EXPORTAS=14;

var PRINT=15;

var windowWidth=null;
var windowHeight=null;
var NS = null;
var IE = null;
var str=null;
var textSetted=null;

NS = (document.layers)? true:false;
IE = (document.all)? true:false;

// function for calculating the right dimensions of a HTML textarea
function getDimensions() {
	if( NS==true ) {
		windowWidth = innerWidth;
		windowHeight = innerHeight;
	}
	else if( IE==true ) {
		windowWidth = document.body.clientWidth;
		windowHeight = document.body.clientHeight;
	}
	windowWidth = Math.round(windowWidth/8.5);
	windowHeight = Math.round(windowHeight/19);
}

// to load the file content into the editor
function setText()
{
	  if(! textSetted )
	  {
		 if (IE)
	   		document.all.edit1.Text = unescape("<#=content#>");
		 else if (NS)
			document.EDITTEXT.TextEditor.value = unescape(code);
	   	textSetted = true;
	}
}

// Function action on button click
function doEdit(para)
{
	switch(para)
	{
	case 1:
	{
		top.close();
		break;
	}
	case 2:
	{
		history.back();
		break;
	}
	case 3:
	{
		//	history.back();
			break;
	}

	case 4:
	{
		document.all.edit1.Undo();
		break;
	}
	case 5:
	{
		document.all.edit1.Redo();
		break;
	}
	case 6:
	{
		document.all.edit1.ShowFindDialog();
		break;
	}
	case 7:
	{
		document.all.edit1.ShowReplaceDialog();
		break;
	}
	case 8:
	{
		document.all.edit1.ShowGotoLineDialog();
		break;
	}
	case 9:
	{
		document.all.edit1.CutToClipboard();
		break;
	}
	case 10:
	{
		document.all.edit1.CopyToClipboard();
		break;
	}
	case 11:
	{
		document.all.edit1.PasteFromClipboard();
		break;
	}
	case 12:
	{
	    document.all.edit1.OpenFile();
		break;
	}
	case 13:
	{
	    document.all.edit1.SaveFile();
		break;
	}
	case 14:
	{
	    document.all.edit1.SaveFileAs();
		break;
	}
	case 15:
	{
	    document.all.edit1.PrintText();
		break;
	}
	default:
	{
		alert("NYI");
		break;
	}
}
	document.all.edit1.focus();
}<|endoftext|>


<commit_before><commit_msg>PT-3945: The variant's cDNA field may contain extra spaces and wrong prefixes Avoid saving duplicate cDNAs with leading/trailing spaces or differed by casing<commit_after><|endoftext|>


<commit_before>import React from 'react';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import gql from 'graphql-tag';

const deferQuery = `# This is a sample query with defer directive.
# The GraphQL Giraffe server is configured to return deferred results after 5 seconds,
# so you can observe better how the effects of a defer directive works.

query TestQuery {
    hero(id:"1000") {
        id,
        name,
        appearsIn,
        homePlanet,
        friends @defer {
            id,
            name
        }
    }
}`;

const streamQuery = `# This is a sample query with stream and defer directive.
# The GraphQL Giraffe server is configured to return each result after 5 seconds,
# so you can observe better how the effects of stream and defer directives work.

query TestQuery {
    hero(id:"1000") {
        name,
        appearsIn,
        homePlanet @defer,
        friends @stream {
            ... on Human {
              name
            }
          	... on Droid {
              name
              primaryFunction
            }
        }
    }
}`

const thresholdQuery = `# This is a sample query that will be denied by a query complexity threshold middleware.
# The field "friends" of both Human and Droid have a query weight of 0.5.
# The maximum query weight (threshold) is set to 2.0 on the server.
# Hero friends will have a weight of 0.5.
# Friends of hero friends will have a weight of 1.0 (since it can be both Human and Droid).
# Also, their inner friends will have a weight of 1.0
# Total weight is 2.5, making the query too complex for the threshold meter.

query TestQuery {
    hero(id:"1000") {
        id, friends { id, friends { id, friends { id } } }
    }
}`

export default class QueryRunner extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            query: deferQuery,
            client: new ApolloClient({
                link: new SubscriptionClient('ws://localhost:8084/', {
                        reconnect: true
                }),
                cache: new InMemoryCache()
            }),
            results : ''
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleRun = this.handleRun.bind(this);
        this.handleSampleQueryChange = this.handleSampleQueryChange.bind(this);
    }

    handleChange(event) {
        this.setState({ query: event.target.value });
    }

    handleSampleQueryChange(event) {
        switch (event.target.value)
        {
            case "defer":
                this.setState({ query: deferQuery });
                break;
            case "stream":
                this.setState({ query: streamQuery });
                break;
            case "threshold" :
                this.setState( {query: thresholdQuery });
                break;
            default:
                break;
        }
    }

    handleRun(event) {
        this.setState({ results: '' });
        this.state.client.subscribe({
            query: gql`${this.state.query}`,
            variables: {}
        }).subscribe({
            next: result => {
                this.setState({ results: this.state.results + JSON.stringify(result) + "\n\n" });
            },
            error: e => {
                this.setState({ results: this.state.results + JSON.stringify(e) + "\n\n" });
            }
        });
        event.preventDefault();
    }

    render() {
        return (

                        Type a query here, or select one of the sample queries in the selection below.
                        You can type subscriptions and defer directives,
                        the client will wait for more responses over Web Socket connection.

Once typed, just click "Run query" to connect to the socket and wait for responses.

                        Sample queries:
                        <select onChange={this.handleSampleQueryChange}>
                            <option value="defer">Deferred query sample</option>
                            <option value="stream">Streamed query sample</option>
                            <option value="threshold">Threshold for complex queries sample</option>
                        </select>

                    <textarea cols="100" rows="20" value={this.state.query} onChange={this.handleChange}></textarea>

                    <button onClick={this.handleRun}>Run query</button>

Results are displayed here.

                        As explained above, queries are run by GraphQL over WebSocket protocol.
                        If the query is a subscription or defer query, the client will wait for subsequent responses from the Socket.

                    <textarea cols="100" rows="20" value={this.state.results}></textarea>

        );
    }
}<commit_msg>Changing sample query text<commit_after>import React from 'react';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import gql from 'graphql-tag';

const deferQuery = `# This is a sample query with defer directive.
# The GraphQL Giraffe server is configured to return deferred results after 5 seconds,
# so you can observe better how the effects of a defer directive works.

query TestQuery {
    hero(id:"1000") {
        id,
        name,
        appearsIn,
        homePlanet,
        friends @defer {
            id,
            name
        }
    }
}`;

const streamQuery = `# This is a sample query with stream and defer directive.
# The GraphQL Giraffe server is configured to return each result after 5 seconds,
# so you can observe better how the effects of stream and defer directives work.

query TestQuery {
    hero(id:"1000") {
        name,
        appearsIn,
        homePlanet @defer,
        friends @stream {
            ... on Human {
              name
            }
          	... on Droid {
              name
              primaryFunction
            }
        }
    }
}`

const thresholdQuery = `# This is a sample query that will be denied by a query complexity threshold middleware.
# The field "friends" of both Human and Droid have a query weight of 0.5.
# The maximum query weight (threshold) is set to 2.0 on the server.
# Hero friends will have a weight of 0.5.
# Friends of friends of hero will have a weight of 1.0 (since they can be both Human and Droid).
# Also, their inner friends will have a weight of 1.0.
# Total weight is 2.5, making the query too complex for the threshold meter.

query TestQuery {
    hero(id:"1000") {
        id, friends { id, friends { id, friends { id } } }
    }
}`

export default class QueryRunner extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            query: deferQuery,
            client: new ApolloClient({
                link: new SubscriptionClient('ws://localhost:8084/', {
                        reconnect: true
                }),
                cache: new InMemoryCache()
            }),
            results : ''
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleRun = this.handleRun.bind(this);
        this.handleSampleQueryChange = this.handleSampleQueryChange.bind(this);
    }

    handleChange(event) {
        this.setState({ query: event.target.value });
    }

    handleSampleQueryChange(event) {
        switch (event.target.value)
        {
            case "defer":
                this.setState({ query: deferQuery });
                break;
            case "stream":
                this.setState({ query: streamQuery });
                break;
            case "threshold" :
                this.setState( {query: thresholdQuery });
                break;
            default:
                break;
        }
    }

    handleRun(event) {
        this.setState({ results: '' });
        this.state.client.subscribe({
            query: gql`${this.state.query}`,
            variables: {}
        }).subscribe({
            next: result => {
                this.setState({ results: this.state.results + JSON.stringify(result) + "\n\n" });
            },
            error: e => {
                this.setState({ results: this.state.results + JSON.stringify(e) + "\n\n" });
            }
        });
        event.preventDefault();
    }

    render() {
        return (

                        Type a query here, or select one of the sample queries in the selection below.
                        You can type subscriptions and defer directives,
                        the client will wait for more responses over Web Socket connection.

Once typed, just click "Run query" to connect to the socket and wait for responses.

                        Sample queries:
                        <select onChange={this.handleSampleQueryChange}>
                            <option value="defer">Deferred query sample</option>
                            <option value="stream">Streamed query sample</option>
                            <option value="threshold">Threshold for complex queries sample</option>
                        </select>

                    <textarea cols="100" rows="20" value={this.state.query} onChange={this.handleChange}></textarea>

                    <button onClick={this.handleRun}>Run query</button>

Results are displayed here.

                        As explained above, queries are run by GraphQL over WebSocket protocol.
                        If the query is a subscription or defer query, the client will wait for subsequent responses from the Socket.

                    <textarea cols="100" rows="20" value={this.state.results}></textarea>

        );
    }
}<|endoftext|>


<commit_before>var MongoClient = require('mongodb').MongoClient
var url = "mongodb://localhost:27017/JuicyData"

var apiKey = require('../config/apiKey.js')
var axios = require('axios')
var toaApi = axios.create({
	baseURL: 'http://theorangealliance.org/apiv2/',
	timeout: 10000,
	headers: {'X-Application-Origin': 'JuicyData', 'X-TOA-Key': apiKey}
})
var eventKeys = [
	'1718-NCAL-RWC',

	'1718-FIM-CMP1',	//team 5386
	'1718-FIM-MARY',
	'1718-FIM-GLBR'
	] //Currently ongoing events

module.exports = function() {
	getData()
}

function getData() {
	MongoClient.connect(url, function(err, db) {
		if (err) throw err
		let matchDatas = {}
		let gameDatas = {red: {}, blue: {}}
		for (let eventKey of eventKeys) {
			db.collection('events').findOne({'_id': eventKey}, function(err, data) {
				if (err) throw err
				let eventInformation = null
				if (data) {
					eventInformation = data._id
				} else {
					console.log('No event in database for TOA event key ' + eventKey)
				}
				toaApi.get('/event/' + eventKey + '/matches').then(function(response) {
					let matches = response.data
					let matchNumbers = []
					let relevantMatches = {}
					matchDatas[eventKey] = {}
					gameDatas.red[eventKey] = {}
					gameDatas.blue[eventKey] = {}
					for (let match of matches) {
						let matchNumber = match.match_name.split('Quals ')[1]
						if (matchNumber) {
							if (!matchNumbers.includes(matchNumber)) {
								matchNumbers.push(Number(matchNumber))
							}
							relevantMatches[matchNumber] = match
						}
					}
					for (let matchNumber of matchNumbers) {
						let match = relevantMatches[matchNumber]
						toaApi.get('/match/' + match.match_key + '/stations').then(function(response) {
							let stations = response.data
							let teams = {
								red: [],
								blue: []
							}
							for (let station of stations) {
								allianceCode = station.station_key.charAt(station.station_key.length-2)
								if (allianceCode === 'R') {
									teams.red.push(Number(station.team_key))
								} else if (allianceCode === 'B') {
									teams.blue.push(Number(station.team_key))
								}
							}

							let matchData = {
								_id:{
									toaEventKey: eventKey,
									matchInformation:{
										matchNumber: Number(matchNumber),
										teams: {
											red1: teams.red[0],
											red2: teams.red[1],
											blue1: teams.blue[0],
											blue2: teams.blue[1]
										}
									}
								},
								resultInformation:{
									winner: match.red_score > match.blue_score ? 'red' : match.blue_score > match.red_score ? 'blue' : 'tie', //Pls check latter if "score" indlues penailtyes for this caluclation
									score:{
										auto:{
											red: match.red_auto_score,
											blue: match.blue_auto_score
										},
										driver:{
											red: match.red_tele_score,
											blue: match.blue_tele_score
										},
										end:{
											red: match.red_end_score,
											blue: match.blue_end_score
										},
										total:{
											// red: match.red_score - match.blue_penalty, //I think that blue penialty is the penailty blue gets
											// blue: match.blue_score - match.red_penalty //And score is their total (penailty + score)
											red: match.red_auto_score + match.red_tele_score + match.red_end_score,
											blue: match.blue_auto_score + match.blue_tele_score + match.blue_end_score
										},
										penalty:{
											red: match.red_penalty,
											blue: match.blue_penalty
										},
										final:{
											red: match.red_score,
											blue: match.blue_score
										}
									}
								}
							}
							saveMatchData(db, matchData, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas)

							toaApi.get('/match/' + match.match_key + '/details').then(function(response) {
								let matchDetails = response.data[0]
								for (let alliance of ['red', 'blue']) {
									let gameData = {
										_id:{
											toaEventKey: eventKey,
											matchInformation:{
												matchNumber: matchNumber,
												robotAlliance: alliance, //blue or red; with lower case
												teams: teams[alliance]
											}
										},
										gameInformation:{	//CHECK IF ALL THSES TYPES ARE CORRECT AND ALSO HAVE COFRRECT MEANING!
											auto:{
												jewel: matchDetails[alliance+'_auto_jewel'],
												glyphs: matchDetails[alliance+'_auto_glyphs'],
												keys: matchDetails[alliance+'_auto_keys'],
												park: matchDetails[alliance+'_auto_park']
											},
											driver:{
												glyphs: matchDetails[alliance+'_tele_glyphs'],
												rows: matchDetails[alliance+'_tele_rows'],
												columns: matchDetails[alliance+'_tele_columns'],
												cypher: matchDetails[alliance+'_tele_cypher']
											},
											end:{
												relic1: matchDetails[alliance+'_end_relic_one'],	//Amount of relics in that zone
												relic2: matchDetails[alliance+'_end_relic_two'],
												relic3: matchDetails[alliance+'_end_relic_three'],
												relicsUp: matchDetails[alliance+'_end_relic_up'],	//Amount of relects standing up
												balanced: matchDetails[alliance+'_end_robot_bal']	//How many robots are balanced
											}
										}
									}
									saveGameData(db, gameData, alliance, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas)
								}
							})
						})
					}
				})
			})
		}
	})
	// setTimeout(getData, 180000) Do it all again in 3 minutes
}

function saveMatchData(db, matchData, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas) {
  	db.collection('matchData').save(matchData, function(err, res) {
    	if (err) throw err
    	matchDatas[eventKey][matchNumber] = matchData
    	finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas)
  	})
}

function saveGameData(db, gameData, alliance, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas) {
  	db.collection('gameData').save(gameData, function(err, res) {
    	if (err) throw err
    	gameDatas[alliance][eventKey][matchNumber] = gameData
    	finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas)
  	})
}

function finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas) {
	for (let eventKey of eventKeys) {
		for (let matchNumber of matchNumbers) {
			if (!matchDatas[eventKey][matchNumber] || !gameDatas.red[eventKey][matchNumber] || !gameDatas.blue[eventKey][matchNumber]) {
				return
			}
		}
	}
	db.close()
	printDatas(eventKeys, matchNumbers, matchDatas, gameDatas)
}

function printDatas(eventKeys, matchNumbers, matchDatas, gameDatas) {
	for (let eventKey of eventKeys) {
		for (let matchNumber of matchNumbers) {
			console.log(eventKey + ' Match ' + matchNumber + ' matchData:')
			console.log(JSON.stringify(matchDatas[eventKey][matchNumber], null, 2))
			console.log()
			console.log(eventKey + ' Match ' + matchNumber + ' red gameData:')
			console.log(JSON.stringify(gameDatas.red[eventKey][matchNumber], null, 2))
			console.log()
			console.log(eventKey + ' Match ' + matchNumber + ' blue gameData:')
			console.log(JSON.stringify(gameDatas.blue[eventKey][matchNumber], null, 2))
			console.log()
			console.log()
		}
	}
}<commit_msg>Partially fixed matchAndGameData<commit_after>var MongoClient = require('mongodb').MongoClient
var url = "mongodb://localhost:27017/JuicyData"

var apiKey = require('../config/apiKey.js')
var axios = require('axios')
var toaApi = axios.create({
	baseURL: 'http://theorangealliance.org/apiv2/',
	timeout: 10000,
	headers: {'X-Application-Origin': 'JuicyData', 'X-TOA-Key': apiKey}
})
var eventKeys = [
	'1718-NCAL-RWC',

	'1718-FIM-CMP1',	//team 5386
	'1718-FIM-MARY',
	'1718-FIM-GLBR'
	] //Currently ongoing events

module.exports = function() {
	getData()
}

function getData() {
	MongoClient.connect(url, function(err, db) {
		if (err) throw err
		let matchDatas = {}
		let gameDatas = {red: {}, blue: {}}
		let matchNumbers = {}
		for (let eventKey of eventKeys) {
			db.collection('events').findOne({'_id': eventKey}, function(err, data) {
				if (err) throw err
				let eventInformation = null
				if (data) {
					eventInformation = data._id
				} else {
					console.log('No event in database for TOA event key ' + eventKey)
				}
				toaApi.get('/event/' + eventKey + '/matches').then(function(response) {
					let matches = response.data
					matchNumbers[eventKey] = []
					let relevantMatches = {}
					matchDatas[eventKey] = {}
					gameDatas.red[eventKey] = {}
					gameDatas.blue[eventKey] = {}
					for (let match of matches) {
						let matchNumber = match.match_name.split('Quals ')[1]
						if (matchNumber) {
							if (!matchNumbers[eventKey].includes(matchNumber)) {
								matchNumbers[eventKey].push(Number(matchNumber))
							}
							relevantMatches[matchNumber] = match
						}
					}
					for (let matchNumber of matchNumbers[eventKey]) {
						let match = relevantMatches[matchNumber]
						toaApi.get('/match/' + match.match_key + '/stations').then(function(response) {
							let stations = response.data
							let teams = {
								red: [],
								blue: []
							}
							for (let station of stations) {
								allianceCode = station.station_key.charAt(station.station_key.length-2)
								if (allianceCode === 'R') {
									teams.red.push(Number(station.team_key))
								} else if (allianceCode === 'B') {
									teams.blue.push(Number(station.team_key))
								}
							}

							let matchData = {
								_id:{
									toaEventKey: eventKey,
									matchInformation:{
										matchNumber: Number(matchNumber),
										teams: {
											red1: teams.red[0],
											red2: teams.red[1],
											blue1: teams.blue[0],
											blue2: teams.blue[1]
										}
									}
								},
								resultInformation:{
									winner: match.red_score > match.blue_score ? 'red' : match.blue_score > match.red_score ? 'blue' : 'tie', //Pls check latter if "score" indlues penailtyes for this caluclation
									score:{
										auto:{
											red: match.red_auto_score,
											blue: match.blue_auto_score
										},
										driver:{
											red: match.red_tele_score,
											blue: match.blue_tele_score
										},
										end:{
											red: match.red_end_score,
											blue: match.blue_end_score
										},
										total:{
											// red: match.red_score - match.blue_penalty, //I think that blue penialty is the penailty blue gets
											// blue: match.blue_score - match.red_penalty //And score is their total (penailty + score)
											red: match.red_auto_score + match.red_tele_score + match.red_end_score,
											blue: match.blue_auto_score + match.blue_tele_score + match.blue_end_score
										},
										penalty:{
											red: match.red_penalty,
											blue: match.blue_penalty
										},
										final:{
											red: match.red_score,
											blue: match.blue_score
										}
									}
								}
							}
							saveMatchData(db, matchData, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas)

							toaApi.get('/match/' + match.match_key + '/details').then(function(response) {
								let matchDetails = response.data[0]
								for (let alliance of ['red', 'blue']) {
									let gameData = {
										_id:{
											toaEventKey: eventKey,
											matchInformation:{
												matchNumber: matchNumber,
												robotAlliance: alliance, //blue or red; with lower case
												teams: teams[alliance]
											}
										},
										gameInformation:{	//CHECK IF ALL THSES TYPES ARE CORRECT AND ALSO HAVE COFRRECT MEANING!
											auto:{
												jewel: matchDetails[alliance+'_auto_jewel'],
												glyphs: matchDetails[alliance+'_auto_glyphs'],
												keys: matchDetails[alliance+'_auto_keys'],
												park: matchDetails[alliance+'_auto_park']
											},
											driver:{
												glyphs: matchDetails[alliance+'_tele_glyphs'],
												rows: matchDetails[alliance+'_tele_rows'],
												columns: matchDetails[alliance+'_tele_columns'],
												cypher: matchDetails[alliance+'_tele_cypher']
											},
											end:{
												relic1: matchDetails[alliance+'_end_relic_one'],	//Amount of relics in that zone
												relic2: matchDetails[alliance+'_end_relic_two'],
												relic3: matchDetails[alliance+'_end_relic_three'],
												relicsUp: matchDetails[alliance+'_end_relic_up'],	//Amount of relects standing up
												balanced: matchDetails[alliance+'_end_robot_bal']	//How many robots are balanced
											}
										}
									}
									saveGameData(db, gameData, alliance, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas)
								}
							})
						})
					}
				})
			})
		}
	})
	// setTimeout(getData, 180000) Do it all again in 3 minutes
}

function saveMatchData(db, matchData, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas) {
  	db.collection('matchData').save(matchData, function(err, res) {
    	if (err) throw err
    	matchDatas[eventKey][matchNumber] = matchData
    	finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas)
  	})
}

function saveGameData(db, gameData, alliance, eventKey, matchNumber, eventKeys, matchNumbers, matchDatas, gameDatas) {
  	db.collection('gameData').save(gameData, function(err, res) {
    	if (err) throw err
    	gameDatas[alliance][eventKey][matchNumber] = gameData
    	finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas)
  	})
}

function finishIfDone(db, eventKeys, matchNumbers, matchDatas, gameDatas) {
	for (let eventKey of eventKeys) {
		for (let matchNumber of matchNumbers[eventKey]) {
			if (!matchDatas[eventKey][matchNumber] || !gameDatas.red[eventKey][matchNumber] || !gameDatas.blue[eventKey][matchNumber]) {
				return
			}
		}
	}
	db.close()
	printDatas(eventKeys, matchNumbers, matchDatas, gameDatas)
}

function printDatas(eventKeys, matchNumbers, matchDatas, gameDatas) {
	for (let eventKey of eventKeys) {
		for (let matchNumber of matchNumbers[eventKey]) {
			console.log(eventKey + ' Match ' + matchNumber + ' matchData:')
			console.log(JSON.stringify(matchDatas[eventKey][matchNumber], null, 2))
			console.log()
			console.log(eventKey + ' Match ' + matchNumber + ' red gameData:')
			console.log(JSON.stringify(gameDatas.red[eventKey][matchNumber], null, 2))
			console.log()
			console.log(eventKey + ' Match ' + matchNumber + ' blue gameData:')
			console.log(JSON.stringify(gameDatas.blue[eventKey][matchNumber], null, 2))
			console.log()
			console.log()
		}
		console.log()
	}
}<|endoftext|>


<commit_before>goog.provide('ng.tryton.fulfil');
goog.provide('ng.tryton.fulfil.datatype');

goog.require('goog.date.Date');
goog.require('goog.date.DateTime');
goog.require('goog.date.UtcDateTime');
goog.require('goog.date.Interval');

goog.scope(function() {
  'use strict';

  var Fulfil = ng.tryton.fulfil;
  Fulfil.datatype = {};  // Need to initialize with Object for compilation
  var dateTime = goog.date.DateTime;
  var utcDateTime = goog.date.UtcDateTime;
  var interval = goog.date.Interval;

  Fulfil.reviver = function (key, value) {
    /*
     * Transform server data for client
     */
    if (value === null) {
      return null;
    }
    if (value['__class__'] === undefined) {
      return value;
    }
    var __class__ = value['__class__'].toLowerCase();

    if (__class__ === 'decimal') {
      var result = new Fulfil.datatype.Decimal(value.decimal);
      if (isNaN(result) || value === '' || value === null) {
          return null;
      } else {
          return result;
      }
    }

    if (__class__ === 'datetime') {
      return new Fulfil.datatype.DateTime(
        value.year,
        value.month && value.month - 1,
        value.day,
        value.hour,
        value.minute,
        value.second,
        value.microsecond && value.microsecond / 1000,
        true
      );
    }
    if (__class__ === 'date') {
      return new Fulfil.datatype.Date(
        value.year,
        value.month && value.month - 1,
        value.day
      );
    }
    if (__class__ === 'time') {
      return new Fulfil.datatype.Time(
        value.hour,
        value.minute,
        value.second,
        value.microsecond && value.microsecond / 1000
      );
    }
    if (__class__ === 'buffer') {
      // TODO: Handle buffer
    }
    return value;
  };

  Fulfil.toJson = function (value) {
    return angular.toJson(Fulfil.transformRequest(value));
  };
  Fulfil.transformRequest = function (value) {
    if (!goog.isDefAndNotNull(value)) {
      return value;
    }
    if (goog.isArray(value)) {
      return value.map(function (item) {
        return Fulfil.transformRequest(item);
      });
    }
    if (value.isDate) {
      return {
        '__class__': 'date',
        'year': value.getYear(),
        'month': value.getMonth() + 1,
        'day': value.getDate()
      };
    }
    if (value.isDateTime) {
      value = value.clone();
      return {
        '__class__': 'datetime',
        'year': value.getUTCFullYear(),
        'month': value.getUTCMonth() + 1,
        'day': value.getUTCDate(),
        'hour': value.getUTCHours(),
        'minute': value.getUTCMinutes(),
        'second': value.getUTCSeconds(),
        'microsecond': value.getUTCMilliseconds() * 1000
      };
    }
    if (value.isTime) {
      return {
        '__class__': 'time',
        'hour': value.getHours(),
        'minute': value.getMinutes(),
        'second': value.getSeconds(),
        'microsecond': value.getMilliseconds() * 1000
      }
    }
    if (value.isTimeDelta) {
      // XXX: getTotalSeconds()
      // Gets the total number of seconds in the time interval.
      // Assumes that months and years are empty.
      return {
        '__class__': 'timedelta',
        'seconds': value.getTotalSeconds()
      };
    }
    if (value instanceof Fulfil.datatype.Decimal) {
      return {
        '__class__': 'Decimal',
        'decimal': value.toString()
      };
    }
    if (value instanceof Uint8Array) {
      var strings = [], chunksize = 0xffff;
      // JavaScript Core has hard-coded argument limit of 65536
      // String.fromCharCode can not be called with too many
      // arguments
      for (var j = 0; j * chunksize < value.length; j++) {
        strings.push(String.fromCharCode.apply(
          null, value.subarray(
            j * chunksize, (j + 1) * chunksize)));
      }
      return {
        '__class__': 'bytes',
        'base64': btoa(strings.join(''))
      };
    }

    if (goog.isObject(value)) {
      var transformed_res = {};
      for (var key in value) {
        if (value.hasOwnProperty(key)) {
          transformed_res[key] = Fulfil.transformRequest(value[key]);
        }
      }
      return transformed_res;
    }
    return value;
  };

  Fulfil.fromJson = function (value) {
    return Fulfil.transformResponse(angular.fromJson(value));
  };
  Fulfil.transformResponse = function (response_obj) {
    /*
     * This method transforms response from tryton server and replace
     * Result to Fulfil Datatypes
     */
    if (!goog.isObject(response_obj)) {
      return response_obj;
    }

    if (goog.isArray(response_obj)) {
      return response_obj.map(function (item) {
        return Fulfil.transformResponse(item);
      });
    }

    var transformed_res = {};

    for (var key in response_obj) {
      if (response_obj.hasOwnProperty(key)) {
        var value = response_obj[key];
        if (typeof value == "object") {
          transformed_res[key] = Fulfil.transformResponse(value);
        }
        else {
          transformed_res[key] = Fulfil.reviver(key, value);
        }
      }
    }
    transformed_res = Fulfil.reviver(null, transformed_res);
    return transformed_res;
  };

  // Browser compatibility: polyfill
  if (!('contains' in String.prototype)) {
    String.prototype.contains = function (str, startIndex) {
      return -1 !== String.prototype.indexOf.call(this, str, startIndex);
    };
  }
  if (!String.prototype.startsWith) {
    Object.defineProperty(String.prototype, 'startsWith', {
      enumerable: false,
      configurable: false,
      writable: false,
      value: function (searchString, position) {
        position = position || 0;
        return this.indexOf(searchString, position) === position;
      }
    });
  }
  if (!String.prototype.endsWith) {
    Object.defineProperty(String.prototype, 'endsWith', {
      enumerable: false,
      configurable: false,
      writable: false,
      value: function (searchString, position) {
        position = position || this.length;
        position = position - searchString.length;
        var lastIndex = this.lastIndexOf(searchString);
        return lastIndex !== -1 && lastIndex === position;
      }
    });
  }

  /*
   * Number field
   */
  Fulfil.datatype.Decimal = Number;

  /*
   * Date field
   */
  Fulfil.datatype.Date = function (year, month, day) {
    var date = new goog.date.Date(year, month, day);
    date.isDate = true;
    return date;
  };

  Fulfil.datatype.Date.clone = function (date) {
    var value = date.clone();
    value.isDate = true;
    return value;
  };
  Fulfil.datatype.Date.min = dateTime.fromTimestamp(-100000000 * 86400000);
  Fulfil.datatype.Date.min.setHours(0);
  Fulfil.datatype.Date.min.setMinutes(0);
  Fulfil.datatype.Date.min.setSeconds(0);
  Fulfil.datatype.Date.min.setMilliseconds(0);
  Fulfil.datatype.Date.min.isDate = true;
  Fulfil.datatype.Date.max = dateTime.fromTimestamp(100000000 * 86400000);
  Fulfil.datatype.Date.max.setHours(0);
  Fulfil.datatype.Date.max.setMinutes(0);
  Fulfil.datatype.Date.max.setSeconds(0);
  Fulfil.datatype.Date.max.setMilliseconds(0);
  Fulfil.datatype.Date.max.isDate = true;

  /*
   * Datetime field
   */
  Fulfil.datatype.DateTime = function (year, month, day, hour, minute, second,
                                       millisecond, utc) {
    var datetime;
    if (utc) {
      datetime = new utcDateTime(
        year, month, day, hour || 0, minute || 0, second || 0, millisecond || 0
      );
    } else {
      datetime = new dateTime(
        year, month, day, hour || 0, minute || 0, second || 0, millisecond || 0
      );
    }
    datetime.isDateTime = true;
    return datetime;
  };

  Fulfil.datatype.DateTime.combine = function (date, time) {
    var datetime = date.clone();
    datetime.setHours(time.getHours());
    datetime.setMinutes(time.getMinutes());
    datetime.setSeconds(time.getSeconds());
    datetime.setMilliseconds(time.getMilliseconds());
    return datetime;
  };

  Fulfil.datatype.DateTime.clone = function (datetime) {
    var value = datetime.clone();
    value.isDateTime = true;
    return value;
  };

  Fulfil.datatype.DateTime.now = function () {
    var value = new dateTime();
    value.isDateTime = true;
    return value;
  };
  Fulfil.datatype.DateTime.min = dateTime.fromTimestamp(-100000000 * 86400000);
  Fulfil.datatype.DateTime.min.isDateTime = true;
  Fulfil.datatype.DateTime.max = dateTime.fromTimestamp(100000000 * 86400000);
  Fulfil.datatype.DateTime.max.isDateTime = true;

  /*
   * Time field
   */
  Fulfil.datatype.Time = function (hour, minute, second, millisecond) {
    var time = new dateTime();
    time.setHours(hour);
    time.setMinutes(minute);
    time.setSeconds(second);
    time.setMilliseconds(millisecond || 0);
    time.isTime = true;
    return time;
  };

  /*
   * Time Delta
   */
  Fulfil.datatype.TimeDelta = function (
      years, months, days, hours, minutes, seconds) {
    var timedelta = new interval(years, months, days, hours, minutes, seconds);
    timedelta.isTimeDelta = true;
    return timedelta;
  };

});
<commit_msg>Fix time datatype<commit_after>goog.provide('ng.tryton.fulfil');
goog.provide('ng.tryton.fulfil.datatype');

goog.require('goog.date.Date');
goog.require('goog.date.DateTime');
goog.require('goog.date.UtcDateTime');
goog.require('goog.date.Interval');

goog.scope(function() {
  'use strict';

  var Fulfil = ng.tryton.fulfil;
  Fulfil.datatype = {};  // Need to initialize with Object for compilation
  var dateTime = goog.date.DateTime;
  var utcDateTime = goog.date.UtcDateTime;
  var interval = goog.date.Interval;

  Fulfil.reviver = function (key, value) {
    /*
     * Transform server data for client
     */
    if (value === null) {
      return null;
    }
    if (value['__class__'] === undefined) {
      return value;
    }
    var __class__ = value['__class__'].toLowerCase();

    if (__class__ === 'decimal') {
      var result = new Fulfil.datatype.Decimal(value.decimal);
      if (isNaN(result) || value === '' || value === null) {
          return null;
      } else {
          return result;
      }
    }

    if (__class__ === 'datetime') {
      return new Fulfil.datatype.DateTime(
        value.year,
        value.month && value.month - 1,
        value.day,
        value.hour,
        value.minute,
        value.second,
        value.microsecond && value.microsecond / 1000,
        true
      );
    }
    if (__class__ === 'date') {
      return new Fulfil.datatype.Date(
        value.year,
        value.month && value.month - 1,
        value.day
      );
    }
    if (__class__ === 'time') {
      return new Fulfil.datatype.Time(
        value.hour,
        value.minute,
        value.second,
        value.microsecond && value.microsecond / 1000
      );
    }
    if (__class__ === 'buffer') {
      // TODO: Handle buffer
    }
    return value;
  };

  Fulfil.toJson = function (value) {
    return angular.toJson(Fulfil.transformRequest(value));
  };
  Fulfil.transformRequest = function (value) {
    if (!goog.isDefAndNotNull(value)) {
      return value;
    }
    if (goog.isArray(value)) {
      return value.map(function (item) {
        return Fulfil.transformRequest(item);
      });
    }
    if (value.isDate) {
      return {
        '__class__': 'date',
        'year': value.getYear(),
        'month': value.getMonth() + 1,
        'day': value.getDate()
      };
    }
    if (value.isDateTime) {
      value = value.clone();
      return {
        '__class__': 'datetime',
        'year': value.getUTCFullYear(),
        'month': value.getUTCMonth() + 1,
        'day': value.getUTCDate(),
        'hour': value.getUTCHours(),
        'minute': value.getUTCMinutes(),
        'second': value.getUTCSeconds(),
        'microsecond': value.getUTCMilliseconds() * 1000
      };
    }
    if (value.isTime) {
      return {
        '__class__': 'time',
        'hour': value.getHours(),
        'minute': value.getMinutes(),
        'second': value.getSeconds(),
        'microsecond': value.getMilliseconds() * 1000
      }
    }
    if (value.isTimeDelta) {
      // XXX: getTotalSeconds()
      // Gets the total number of seconds in the time interval.
      // Assumes that months and years are empty.
      return {
        '__class__': 'timedelta',
        'seconds': value.getTotalSeconds()
      };
    }
    if (value instanceof Fulfil.datatype.Decimal) {
      return {
        '__class__': 'Decimal',
        'decimal': value.toString()
      };
    }
    if (value instanceof Uint8Array) {
      var strings = [], chunksize = 0xffff;
      // JavaScript Core has hard-coded argument limit of 65536
      // String.fromCharCode can not be called with too many
      // arguments
      for (var j = 0; j * chunksize < value.length; j++) {
        strings.push(String.fromCharCode.apply(
          null, value.subarray(
            j * chunksize, (j + 1) * chunksize)));
      }
      return {
        '__class__': 'bytes',
        'base64': btoa(strings.join(''))
      };
    }

    if (goog.isObject(value)) {
      var transformed_res = {};
      for (var key in value) {
        if (value.hasOwnProperty(key)) {
          transformed_res[key] = Fulfil.transformRequest(value[key]);
        }
      }
      return transformed_res;
    }
    return value;
  };

  Fulfil.fromJson = function (value) {
    return Fulfil.transformResponse(angular.fromJson(value));
  };
  Fulfil.transformResponse = function (response_obj) {
    /*
     * This method transforms response from tryton server and replace
     * Result to Fulfil Datatypes
     */
    if (!goog.isObject(response_obj)) {
      return response_obj;
    }

    if (goog.isArray(response_obj)) {
      return response_obj.map(function (item) {
        return Fulfil.transformResponse(item);
      });
    }

    var transformed_res = {};

    for (var key in response_obj) {
      if (response_obj.hasOwnProperty(key)) {
        var value = response_obj[key];
        if (typeof value == "object") {
          transformed_res[key] = Fulfil.transformResponse(value);
        }
        else {
          transformed_res[key] = Fulfil.reviver(key, value);
        }
      }
    }
    transformed_res = Fulfil.reviver(null, transformed_res);
    return transformed_res;
  };

  // Browser compatibility: polyfill
  if (!('contains' in String.prototype)) {
    String.prototype.contains = function (str, startIndex) {
      return -1 !== String.prototype.indexOf.call(this, str, startIndex);
    };
  }
  if (!String.prototype.startsWith) {
    Object.defineProperty(String.prototype, 'startsWith', {
      enumerable: false,
      configurable: false,
      writable: false,
      value: function (searchString, position) {
        position = position || 0;
        return this.indexOf(searchString, position) === position;
      }
    });
  }
  if (!String.prototype.endsWith) {
    Object.defineProperty(String.prototype, 'endsWith', {
      enumerable: false,
      configurable: false,
      writable: false,
      value: function (searchString, position) {
        position = position || this.length;
        position = position - searchString.length;
        var lastIndex = this.lastIndexOf(searchString);
        return lastIndex !== -1 && lastIndex === position;
      }
    });
  }

  /*
   * Number field
   */
  Fulfil.datatype.Decimal = Number;

  /*
   * Date field
   */
  Fulfil.datatype.Date = function (year, month, day) {
    var date = new goog.date.Date(year, month, day);
    date.isDate = true;
    return date;
  };

  Fulfil.datatype.Date.clone = function (date) {
    var value = date.clone();
    value.isDate = true;
    return value;
  };
  Fulfil.datatype.Date.min = dateTime.fromTimestamp(-100000000 * 86400000);
  Fulfil.datatype.Date.min.setHours(0);
  Fulfil.datatype.Date.min.setMinutes(0);
  Fulfil.datatype.Date.min.setSeconds(0);
  Fulfil.datatype.Date.min.setMilliseconds(0);
  Fulfil.datatype.Date.min.isDate = true;
  Fulfil.datatype.Date.max = dateTime.fromTimestamp(100000000 * 86400000);
  Fulfil.datatype.Date.max.setHours(0);
  Fulfil.datatype.Date.max.setMinutes(0);
  Fulfil.datatype.Date.max.setSeconds(0);
  Fulfil.datatype.Date.max.setMilliseconds(0);
  Fulfil.datatype.Date.max.isDate = true;

  /*
   * Datetime field
   */
  Fulfil.datatype.DateTime = function (year, month, day, hour, minute, second,
                                       millisecond, utc) {
    var datetime;
    if (utc) {
      datetime = new utcDateTime(
        year, month, day, hour || 0, minute || 0, second || 0, millisecond || 0
      );
    } else {
      datetime = new dateTime(
        year, month, day, hour || 0, minute || 0, second || 0, millisecond || 0
      );
    }
    datetime.isDateTime = true;
    return datetime;
  };

  Fulfil.datatype.DateTime.combine = function (date, time) {
    var datetime = date.clone();
    datetime.setHours(time.getHours());
    datetime.setMinutes(time.getMinutes());
    datetime.setSeconds(time.getSeconds());
    datetime.setMilliseconds(time.getMilliseconds());
    return datetime;
  };

  Fulfil.datatype.DateTime.clone = function (datetime) {
    var value = datetime.clone();
    value.isDateTime = true;
    return value;
  };

  Fulfil.datatype.DateTime.now = function () {
    var value = new dateTime();
    value.isDateTime = true;
    return value;
  };
  Fulfil.datatype.DateTime.min = dateTime.fromTimestamp(-100000000 * 86400000);
  Fulfil.datatype.DateTime.min.isDateTime = true;
  Fulfil.datatype.DateTime.max = dateTime.fromTimestamp(100000000 * 86400000);
  Fulfil.datatype.DateTime.max.isDateTime = true;

  /*
   * Time field
   */
  Fulfil.datatype.Time = function (hour, minute, second, millisecond) {
    var time = new dateTime();
    if (hour) {
      time.setHours(hour);
    }
    if (minute) {
      time.setMinutes(minute);
    }
    if (second) {
      time.setSeconds(second);
    }
    if (millisecond) {
      time.setMilliseconds(millisecond || 0);
    }
    time.isTime = true;
    return time;
  };
  Fulfil.datatype.Time.clone = function (time) {
    var value = time.clone();
    value.isTime = true;
    return value;
  };

  /*
   * Time Delta
   */
  Fulfil.datatype.TimeDelta = function (
      years, months, days, hours, minutes, seconds) {
    var timedelta = new interval(years, months, days, hours, minutes, seconds);
    timedelta.isTimeDelta = true;
    return timedelta;
  };

});
<|endoftext|>