<commit_before>/*
 * Copyright (c) 1997-2013, SalesLogix, NA., LLC. All rights reserved.
 */

/**
 * @class crm.SpeedSearchWidget
 *
 * @mixins argos._Templated
 *
 */
define('crm/SpeedSearchWidget', [
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/event',
    'dojo/dom-class',
    'dijit/_Widget',
    'argos/_Templated'
], function(
    declare,
    lang,
    event,
    domClass,
    _Widget,
    _Templated
) {
    var __class = declare('crm.SpeedSearchWidget', [_Widget, _Templated], {
        /**
         * @property {Object} attributeMap
         */
        attributeMap: {
            queryValue: {node: 'queryNode', type: 'attribute', attribute: 'value'}
        },

        /**
         * @property {Simplate} widgetTemplate
         */
        widgetTemplate: new Simplate([
            '
',
            '
',
                '
<input type="text" placeholder="{%= $.searchText %}" name="query" class="query" autocorrect="off" autocapitalize="off" data-dojo-attach-point="queryNode" data-dojo-attach-event="onfocus:_onFocus,onblur:_onBlur,onkeypress:_onKeyPress,onmouseup: _onMouseUp" />
',
            '
',
            '
'
        ]),
        /**
         * @property {DOMNode} queryNode HTML input node. The dojo attach point.
         */
        queryNode: null,

        /**
         * @property {String} searchText The placeholder text for the input.
         */
        searchText: 'SpeedSearch',

        _setQueryValueAttr: function(value) {
            this._onFocus();
            this.queryNode.value = value;
        },
        /**
         * Clears the current search query.
         */
        clear: function() {
            domClass.remove(this.domNode, 'search-active');
            this.set('queryValue', '');
        },
        /**
         * Fires onSearchExpression using the current search query.
         */
        search: function() {
            var queryTerm = this.getQuery();
            if (!lang.trim(queryTerm)) {
                return;
            }

            this.onSearchExpression(queryTerm, this);
        },
        /**
         * Returns the current search query.
         * @returns {String}
         */
        getQuery: function() {
            return this.queryNode.value;
        },
        configure: function(options) {
            lang.mixin(this, options);
        },
        _onClearClick: function(evt) {
            event.stop(evt);
            this.clear();
            this.queryNode.focus();
            this.queryNode.click();
        },
        _onBlur: function() {
            domClass.toggle(this.domNode, 'search-active', !!this.queryNode.value);
        },
        _onFocus: function() {
            domClass.add(this.domNode, 'search-active');
        },
        _onMouseUp: function() {
            // Work around a chrome issue where mouseup after a focus will de-select the text
            setTimeout(function() {
                this.queryNode.setSelectionRange(0, 9999);
            }.bind(this), 50);
        },
        _onKeyPress: function(evt) {
            if (evt.keyCode === 13 || evt.keyCode === 10) {
                event.stop(evt);
                this.queryNode.blur();
                this.search();
            }
        },
        /**
         * The event that fires when the search widget provides an explicit search query
         * @param {String} expression
         * @param {Object} widget
         */
        onSearchExpression: function() {
        }
    });

    lang.setObject('Mobile.SalesLogix.SpeedSearchWidget', __class);
    return __class;
});

<commit_msg>Fix speedsearch error. #MBL-10941<commit_after>/*
 * Copyright (c) 1997-2013, SalesLogix, NA., LLC. All rights reserved.
 */

/**
 * @class crm.SpeedSearchWidget
 *
 * @mixins argos._Templated
 *
 */
define('crm/SpeedSearchWidget', [
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/event',
    'dojo/dom-class',
    'dijit/_Widget',
    'argos/_Templated'
], function(
    declare,
    lang,
    event,
    domClass,
    _Widget,
    _Templated
) {
    var __class = declare('crm.SpeedSearchWidget', [_Widget, _Templated], {
        /**
         * @property {Object} attributeMap
         */
        attributeMap: {
            queryValue: {node: 'queryNode', type: 'attribute', attribute: 'value'}
        },

        /**
         * @property {Simplate} widgetTemplate
         */
        widgetTemplate: new Simplate([
            '
',
            '
',
                '
<input type="text" placeholder="{%= $.searchText %}" name="query" class="query" autocorrect="off" autocapitalize="off" data-dojo-attach-point="queryNode" data-dojo-attach-event="onfocus:_onFocus,onblur:_onBlur,onkeypress:_onKeyPress,onmouseup: _onMouseUp" />
',
            '
',
            '
'
        ]),
        /**
         * @property {DOMNode} queryNode HTML input node. The dojo attach point.
         */
        queryNode: null,

        /**
         * @property {String} searchText The placeholder text for the input.
         */
        searchText: 'SpeedSearch',

        _setQueryValueAttr: function(value) {
            this._onFocus();
            this.queryNode.value = value;
        },
        /**
         * Clears the current search query.
         */
        clear: function() {
            domClass.remove(this.domNode, 'search-active');
            this.set('queryValue', '');
        },
        /**
         * Fires onSearchExpression using the current search query.
         */
        search: function() {
            var queryTerm = this.getQuery();
            if (!lang.trim(queryTerm)) {
                return;
            }

            this.onSearchExpression(queryTerm, this);
        },
        /**
         * Returns the current search query.
         * @returns {String}
         */
        getQuery: function() {
            return this.queryNode.value;
        },
        configure: function(options) {
            lang.mixin(this, options);
        },
        _onClearClick: function(evt) {
            event.stop(evt);
            this.clear();
            this.queryNode.focus();
            this.queryNode.click();
        },
        _onBlur: function() {
            domClass.toggle(this.domNode, 'search-active', !!this.queryNode.value);
        },
        _onFocus: function() {
            domClass.add(this.domNode, 'search-active');
        },
        _onMouseUp: function() {
            // Work around a chrome issue where mouseup after a focus will de-select the text
            setTimeout(function() {
                this.queryNode.setSelectionRange(0, 9999);
            }.bind(this), 50);
        },
        _onKeyPress: function(evt) {
            if (evt.keyCode === 13 || evt.keyCode === 10) {
                event.stop(evt);
                this.queryNode.blur();
                this.search();
            }
        },
        /**
         * The event that fires when the search widget provides an explicit search query
         * @param {String} expression
         * @param {Object} widget
         */
        onSearchExpression: function() {
        },
        getFormattedSearchQuery: function() {
            return null;
        }
    });

    lang.setObject('Mobile.SalesLogix.SpeedSearchWidget', __class);
    return __class;
});

<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import UglifyJsPlugin from 'uglifyjs-webpack-plugin'
import {existsSync} from 'fs'
import {getProjectDir, TOOLBOX_DIR} from '../../paths'
import {getSettings} from '../../settings'
import {isProduction} from '../../util'
import {join} from 'path'
import {NamedModulesPlugin} from 'webpack'

// Webpack’s loaders.
import assetRule from './rules/asset'
import cssModuleRule from './rules/css-module'
import cssRule from './rules/css'
import htmlRule from './rules/html'
import jsRule from './rules/js'

const PROJECT_DIR = getProjectDir()
const PROJECT_SRC_DIR = join(PROJECT_DIR, 'src')
const PROJECT_BUILD_DIR = join(PROJECT_DIR, 'build')

const MODULE_PATHS = [
  join(PROJECT_DIR, 'node_modules'),
  join(TOOLBOX_DIR, 'node_modules'),
  join(PROJECT_DIR, 'src'),
  'node_modules',
  'src',
]

let {
  disableSourceMaps,
  minify = false,
  watch = false,
} = getSettings()

/**
 * By default, the shared configuration look for 2 entries, this is useful when
 * your project act both as an app by running the “main.js” and a library by
 * allowing the “index.js” to be imported.
 */
function getDefaultEntries() {
  let result = {}

  if (existsSync(join(PROJECT_SRC_DIR, 'main.js')))
    result.main = 'main'

  if (existsSync(join(PROJECT_SRC_DIR, 'index.js')))
    result.index = 'index'

  return result
}

/**
 * This configuration holds the logic shared across all project types.
 */
export default function () {
  const MINIMIZER = {
    minimizer: [new UglifyJsPlugin()],
  }

  return {
    devServer: {
      contentBase: PROJECT_BUILD_DIR,
      historyApiFallback: true,
      port: 9000,
    },
    devtool: !disableSourceMaps && 'source-map',
    entry: getDefaultEntries(),
    mode: isProduction() ? 'production' : 'development',
    module: {
      rules: [
        assetRule(),
        cssModuleRule(),
        cssRule(),
        htmlRule(),
        jsRule(),
      ],
    },
    node: {
      // Disable polyfills.
      __dirname: false,
      __filename: false,
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      minimize: minify,
      ...minify && MINIMIZER,
    },
    output: {
      path: PROJECT_BUILD_DIR,
      filename: '[name].js',
    },
    performance: {
      hints: isProduction(),
    },
    plugins: [new NamedModulesPlugin()],
    resolve: {
      extensions: [
        '.css',
        '.html',
        '.js',
        '.json',
        '.jsx',
        '.module.css',
      ],
      modules: MODULE_PATHS,
    },
    resolveLoader: {
      modules: MODULE_PATHS,
    },
    stats: {
      // Hide everything first, any property following this one will enable only
      // the features we want.
      all: false,

      // Asset table.
      assets: true,

      // Build date and time.
      builtAt: true,

      // Show errors.
      errors: true,

      // Performance hints.
      performance: isProduction(),

      // Build time.
      timings: true,

      // Webpack version.
      version: true,
    },
    watch,
  }
}
<commit_msg>Cleanup webpack config<commit_after>// Licensed under the Apache License, Version 2.0 (the “License”); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import {
  getProjectName,
  isPathSubDirOf,
  isProduction,
  isWindows,
} from '../../util'

import UglifyJsPlugin from 'uglifyjs-webpack-plugin'
import {existsSync} from 'fs'
import {getProjectDir, TOOLBOX_DIR, TOOLBOX_SRC_DIR} from '../../paths'
import {getSettings} from '../../settings'
import {join, relative} from 'path'
import {NamedModulesPlugin} from 'webpack'

// Webpack’s loaders.
import assetRule from './rules/asset'
import cssModuleRule from './rules/css-module'
import cssRule from './rules/css'
import htmlRule from './rules/html'
import jsRule from './rules/js'

const PROJECT_DIR = getProjectDir()
const PROJECT_SRC_DIR = join(PROJECT_DIR, 'src')
const PROJECT_BUILD_DIR = join(PROJECT_DIR, 'build')

const MODULE_PATHS = [
  join(PROJECT_DIR, 'node_modules'),
  join(TOOLBOX_DIR, 'node_modules'),
  join(PROJECT_DIR, 'src'),
  'node_modules',
  'src',
]

let {
  disableSourceMaps,
  minify = false,
  watch = false,
} = getSettings()

/**
 * By default, the shared configuration look for 2 entries, this is useful when
 * your project act both as an app by running the “main.js” and a library by
 * allowing the “index.js” to be imported.
 */
function getDefaultEntries() {
  let result = {}

  if (existsSync(join(PROJECT_SRC_DIR, 'main.js')))
    result.main = 'main'

  if (existsSync(join(PROJECT_SRC_DIR, 'index.js')))
    result.index = 'index'

  return result
}

const STATS = {
  // Hide everything first, any property following this one will enable only
  // the features we want.
  all: false,

  // Asset table.
  assets: true,

  // Build date and time.
  builtAt: true,

  // Show errors.
  errors: true,

  // Performance hints.
  performance: isProduction(),

  // Build time.
  timings: true,

  // Webpack version.
  version: true,
}

/**
 * This configuration holds the logic shared across all project types.
 */
export default function () {
  const MINIMIZER = {
    minimizer: [new UglifyJsPlugin()],
  }

  return {
    devServer: {
      contentBase: PROJECT_BUILD_DIR,
      historyApiFallback: true,
      port: 9000,
      stats: STATS,
    },
    devtool: !disableSourceMaps && 'source-map',
    entry: getDefaultEntries(),
    mode: isProduction() ? 'production' : 'development',
    module: {
      rules: [
        assetRule(),
        cssModuleRule(),
        cssRule(),
        htmlRule(),
        jsRule(),
      ],
    },
    node: {
      // Disable polyfills.
      __dirname: false,
      __filename: false,
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      minimize: minify,
      ...minify && MINIMIZER,
    },
    output: {
      path: PROJECT_BUILD_DIR,
      filename: '[name].js',
      devtoolModuleFilenameTemplate: info => {
        const PROJECT_NAME = getProjectName()
        let identifier = info.identifier
        let path = info.absoluteResourcePath

        // If the path does not exist on the file system, it is webpack’s URL.
        if (!existsSync(path))
          return `webpack:///${identifier}`

        // Project sources.
        if (isPathSubDirOf(path, PROJECT_DIR)) {
          path = relative(PROJECT_DIR, path)
          return `${PROJECT_NAME}:///${path}`
        }

        // Toolbox sources.
        if (isPathSubDirOf(path, TOOLBOX_DIR)) {
          path = relative(TOOLBOX_DIR, path)
          return `borela:///${path}`
        }

        throw new Error(`Invalid resource path “${path}”.`)
      },
    },
    plugins: [new NamedModulesPlugin()],
    resolve: {
      extensions: [
        '.js',
        '.jsx',
        '.mjs',
        '.json',
        '.module.css',
      ],
      modules: MODULE_PATHS,
    },
    resolveLoader: {
      modules: MODULE_PATHS,
    },
    stats: STATS,
    watch,
  }
}
<|endoftext|>


<commit_before>/**
 * Created by JCJordan on 30/01/2017.
 */

//Get code from json file where data is entry 1, columns selected entry 2, etc.
//Generate statistics and format data
//Create pdf report using generated statistics and data

function genReport(reportData) {
    console.log("generating report...");

    genGraphs(reportData);
}

function genPDF(reportData, graphs) {

    var database = reportData.database;
    var columns = reportData.columns;
    var filters = reportData.filters;
    var filteredDatabase = reportData.filteredDatabase;
    var today = new Date();

    var docDefinition = {
        content: [{
                text: 'Report ' + today.getDate() + "/" + (today.getMonth() + 1) + "/" + today.getFullYear(),
                style: 'header',
                alignment: "center",
                fontSize: 18,
                bold: true
            },
            {
                text: 'Filtered Table',
                style: 'header',
                alignment: "center",
                fontSize: 14,
                bold: true
            },
            filteredTable(filteredDatabase, columns, filters),
            {
                text: '\n\nFilters applied',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                ol: filterList(filters)
            },
            {
                text: '\n\nBase Statistics',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                ol: statisticsList(filteredDatabase)
            },
            {
                text: '\n\nGraphical Data',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                image: graphs,
                width: 400
            }
        ]
    };

    console.log("report generated...");

    // open the PDF in a new window
    pdfMake.createPdf(docDefinition).open();

}

function genGraphs(reportData) {

    //Male to Female Pie Chart
    //Age Range Bar/Pie Chart
    //Area (Living in) Pie Chart

    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    data.addColumn('number', 'Attendance');

    data.addRows([
        [{
            v: new Date(2017, 0, 1),
            f: "1st of Jan"
        }, 1000],
        [{
            v: new Date(2017, 1, 1),
            f: "1st of Feb"
        }, 2000, ],
        [{
            v: new Date(2017, 2, 1),
            f: "1st of March"
        }, 1500],
        [{
            v: new Date(2017, 3, 1),
            f: "1st of April"
        }, 2500],
    ]);

    var options = {
        title: 'Attendance per Month',
        colors: ['#9575cd', '#33ac71'],
        hAxis: {
            title: 'Month',
            //format: 'h:mm a',
            viewWindow: {
                min: new Date(2017, -1, 15),
                max: new Date(2017, 3, 15)
            }
        },
        vAxis: {
            title: 'Attendance'
        }
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
    chart.draw(data, options);
    //google.visualization.events.addListener(chart, 'ready', function () {
    genPDF(reportData, chart.getImageURI());
    //});

}

function filterList(filters) {

    var filterList = [];
    filters.forEach(function(filter) {
        if (filter.type == "contains") {
            filterList.push(filter.column + " contains " + filter.value);
        }
        if (filter.type == "range") {
            filterList.push(filter.column + " is between " + (filter.value).toString().split("%")[0] + " and " + (filter.value).toString().split("%")[1]);
        }
    });
    return filterList;

}

function statisticsList(database) {
    var statistics = statisticCalc(database);
    var statisticsList = [];

    Object.keys(statistics).forEach(function(statistic) {
        statisticsList.push(statistic + " = " + statistics[statistic]);
    });

    return statisticsList;
}

function statisticCalc(database) {
    var statistics = {};
    var total = database.length;
    statistics.total = total;
    var ageRange = {
        20: 0,
        40: 0,
        60: 0,
        80: 0,
        100: 0
    };
    statistics.agerange = ageRange;

    database.forEach(function(entry) {});

    return statistics;
}

function filteredTable(entries, columns) {
    var widths = [];
    columns.forEach(function() {
        widths.push('*');
    });
    return {
        style: 'tableExample',
        color: '#444',
        alignment: "center",
        table: {
            widths: widths,
            headerRows: 1,
            body: buildTableBody(entries, columns)
        },
        layout: 'lightHorizontalLines'
    };
}

function buildTableBody(entries, columns) {

    var body = [];
    var headers = [];

    columns.forEach(function(headerName) {
        headers.push({
            text: headerName,
            style: 'tableHeader',
            alignment: 'center',
            bold: true
        });
    });
    body.push(headers);
    entries.forEach(function(entryData) {
        var entry = [];
        columns.forEach(function(column) {
            entry.push(entryData[column]);
        });
        body.push(entry);
    });

    return body;

}
<commit_msg>Modified report to use Human Readable table headers<commit_after>/**
 * Created by JCJordan on 30/01/2017.
 */

//Get code from json file where data is entry 1, columns selected entry 2, etc.
//Generate statistics and format data
//Create pdf report using generated statistics and data

function genReport(reportData) {
    console.log("generating report...");

    genGraphs(reportData);
}

function genPDF(reportData, graphs) {

    var database = reportData.database;
    var columns = reportData.columns;
    var filters = reportData.filters;
    var filteredDatabase = reportData.filteredDatabase;
    var today = new Date();

    var docDefinition = {
        content: [{
                text: 'Report ' + today.getDate() + "/" + (today.getMonth() + 1) + "/" + today.getFullYear(),
                style: 'header',
                alignment: "center",
                fontSize: 18,
                bold: true
            },
            {
                text: 'Filtered Table',
                style: 'header',
                alignment: "center",
                fontSize: 14,
                bold: true
            },
            filteredTable(filteredDatabase, columns, filters),
            {
                text: '\n\nFilters applied',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                ol: filterList(filters)
            },
            {
                text: '\n\nBase Statistics',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                ol: statisticsList(filteredDatabase)
            },
            {
                text: '\n\nGraphical Data',
                style: 'header',
                fontSize: 14,
                bold: true
            },
            {
                image: graphs,
                width: 400
            }
        ]
    };

    console.log("report generated...");

    // open the PDF in a new window
    pdfMake.createPdf(docDefinition).open();

}

function genGraphs(reportData) {

    //Male to Female Pie Chart
    //Age Range Bar/Pie Chart
    //Area (Living in) Pie Chart

    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    data.addColumn('number', 'Attendance');

    data.addRows([
        [{
            v: new Date(2017, 0, 1),
            f: "1st of Jan"
        }, 1000],
        [{
            v: new Date(2017, 1, 1),
            f: "1st of Feb"
        }, 2000, ],
        [{
            v: new Date(2017, 2, 1),
            f: "1st of March"
        }, 1500],
        [{
            v: new Date(2017, 3, 1),
            f: "1st of April"
        }, 2500],
    ]);

    var options = {
        title: 'Attendance per Month',
        colors: ['#9575cd', '#33ac71'],
        hAxis: {
            title: 'Month',
            //format: 'h:mm a',
            viewWindow: {
                min: new Date(2017, -1, 15),
                max: new Date(2017, 3, 15)
            }
        },
        vAxis: {
            title: 'Attendance'
        }
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
    chart.draw(data, options);
    //google.visualization.events.addListener(chart, 'ready', function () {
    genPDF(reportData, chart.getImageURI());
    //});

}

function filterList(filters) {

    var filterList = [];
    filters.forEach(function(filter) {
        if (filter.type == "contains") {
            filterList.push(filter.column + " contains " + filter.value);
        }
        if (filter.type == "range") {
            filterList.push(filter.column + " is between " + (filter.value).toString().split("%")[0] + " and " + (filter.value).toString().split("%")[1]);
        }
    });
    return filterList;

}

function statisticsList(database) {
    var statistics = statisticCalc(database);
    var statisticsList = [];

    Object.keys(statistics).forEach(function(statistic) {
        statisticsList.push(statistic + " = " + statistics[statistic]);
    });

    return statisticsList;
}

function statisticCalc(database) {
    var statistics = {};
    var total = database.length;
    statistics.total = total;
    var ageRange = {
        20: 0,
        40: 0,
        60: 0,
        80: 0,
        100: 0
    };
    statistics.agerange = ageRange;

    database.forEach(function(entry) {});

    return statistics;
}

function filteredTable(entries, columns) {
    var widths = [];
    columns.forEach(function() {
        widths.push('*');
    });
    return {
        style: 'tableExample',
        color: '#444',
        alignment: "center",
        table: {
            widths: widths,
            headerRows: 1,
            body: buildTableBody(entries, columns)
        },
        layout: 'lightHorizontalLines'
    };
}

function buildTableBody(entries, columns) {

    var body = [];
    var headers = [];

    columns.forEach(function(columnData) {
        headers.push({
            text: columnData.hr,
            style: 'tableHeader',
            alignment: 'center',
            bold: true
        });
    });
    body.push(headers);
    entries.forEach(function(entryData) {
        var entry = [];
        columns.forEach(function(column) {
            entry.push(entryData[column.db]);
        });
        body.push(entry);
    });

    return body;

}
<|endoftext|>


<commit_before>/* Copyright 2019 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

import {NUM_ROWS, NUM_COLUMNS} from './constants.js';
import {Server} from '../../server/modules/module_interface.ts';

export function load(network, debug) {
  class P5GameOfLifeServer extends Server {
    constructor(config) {
      super(config);
      debug('P5GameOfLife Server!', config);

      this.numTicks = 0;
      this.numTicksBetweenIterations = 2;

      this.gameBoard = new Array(NUM_COLUMNS);
      this.tmpBoard = new Array(NUM_COLUMNS);
      for (var i = 0; i < NUM_COLUMNS; i++) {
        this.gameBoard[i] = new Array(NUM_ROWS);
        this.tmpBoard[i] = new Array(NUM_ROWS);
      }
      for (i = 0; i < NUM_COLUMNS; i++) {
        for (var j = 0; j < NUM_ROWS; j++) {
          // Lining the edges with 0s
          if (i === 0 || j === 0 || i == NUM_COLUMNS-1 || j == NUM_ROWS-1) {
            this.gameBoard[i][j] = 0;
          } else {
            // Filling the rest randomly
            this.gameBoard[i][j] = Math.round(Math.random());
          }
          this.tmpBoard[i][j] = 0;
        }
      }
    }

    tick() {
      this.numTicks++;

      if (this.numTicks % this.numTicksBetweenIterations !== 0) {
        return;
      }

      // Update the board and emit it.
      // Loop through every spot in our 2D array and check spots neighbors
      for (var x = 1; x < NUM_COLUMNS - 1; x++) {
        for (var y = 1; y < NUM_ROWS - 1; y++) {
          // Add up all the states in a 3x3 surrounding grid
          var neighbors = 0;
          for (var i = -1; i <= 1; i++) {
            for (var j = -1; j <= 1; j++) {
              neighbors += this.gameBoard[x+i][y+j];
            }
          }

          // A little trick to subtract the current cell's state since
          // we added it in the above loop
          neighbors -= this.gameBoard[x][y];
          // Rules of Life
          if (this.gameBoard[x][y] == 1 && neighbors <  2) {
            // Died of loneliness.
            this.tmpBoard[x][y] = 0;
          } else if (this.gameBoard[x][y] == 1 && neighbors >  3) {
            // Died of overpopulation.
            this.tmpBoard[x][y] = 0;
          } else if (this.gameBoard[x][y] === 0 && neighbors == 3) {
            // Reproduction!
            this.tmpBoard[x][y] = 1;
          } else {
            // Stasis.
            this.tmpBoard[x][y] = this.gameBoard[x][y];
          }
        }
      }

      // Swap!
      var temp = this.gameBoard;
      this.gameBoard = this.tmpBoard;
      this.tmpBoard = temp;

      network.send('board', {
        board : this.gameBoard,
      });
    }
  }

  return {server: P5GameOfLifeServer};
}
<commit_msg>Fix life<commit_after>/* Copyright 2019 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

import {NUM_ROWS, NUM_COLUMNS} from './constants.js';
import {Server} from '../../server/modules/module_interface.ts';

export function load(network, debug) {
  class P5GameOfLifeServer extends Server {
    constructor(config) {
      super(config);
      debug('P5GameOfLife Server!', config);

      this.numTicks = 0;
      this.numTicksBetweenIterations = 2;

      this.gameBoard = new Array(NUM_COLUMNS);
      this.tmpBoard = new Array(NUM_COLUMNS);
      for (let i = 0; i < NUM_COLUMNS; i++) {
        this.gameBoard[i] = new Array(NUM_ROWS);
        this.tmpBoard[i] = new Array(NUM_ROWS);
      }
      for (let i = 0; i < NUM_COLUMNS; i++) {
        for (let j = 0; j < NUM_ROWS; j++) {
          // Lining the edges with 0s
          if (i === 0 || j === 0 || i == NUM_COLUMNS-1 || j == NUM_ROWS-1) {
            this.gameBoard[i][j] = 0;
          } else {
            // Filling the rest randomly
            this.gameBoard[i][j] = Math.round(Math.random());
          }
          this.tmpBoard[i][j] = 0;
        }
      }
    }

    tick() {
      this.numTicks++;

      if (this.numTicks % this.numTicksBetweenIterations !== 0) {
        return;
      }

      // Update the board and emit it.
      // Loop through every spot in our 2D array and check spots neighbors
      for (let x = 1; x < NUM_COLUMNS - 1; x++) {
        for (let y = 1; y < NUM_ROWS - 1; y++) {
          // Add up all the states in a 3x3 surrounding grid
          let neighbors = 0;
          for (let i = -1; i <= 1; i++) {
            for (let j = -1; j <= 1; j++) {
              neighbors += this.gameBoard[x+i][y+j];
            }
          }

          // A little trick to subtract the current cell's state since
          // we added it in the above loop
          neighbors -= this.gameBoard[x][y];
          // Rules of Life
          if (this.gameBoard[x][y] == 1 && neighbors <  2) {
            // Died of loneliness.
            this.tmpBoard[x][y] = 0;
          } else if (this.gameBoard[x][y] == 1 && neighbors >  3) {
            // Died of overpopulation.
            this.tmpBoard[x][y] = 0;
          } else if (this.gameBoard[x][y] === 0 && neighbors == 3) {
            // Reproduction!
            this.tmpBoard[x][y] = 1;
          } else {
            // Stasis.
            this.tmpBoard[x][y] = this.gameBoard[x][y];
          }
        }
      }

      // Swap!
      const temp = this.gameBoard;
      this.gameBoard = this.tmpBoard;
      this.tmpBoard = temp;

      network.sendToAllClients('board', {
        board : this.gameBoard,
      });
    }
  }

  return {server: P5GameOfLifeServer};
}
<|endoftext|>


<commit_before>import {assert} from 'chai';
import bel from 'bel';
import domEvents from 'dom-events';
import augment from '../../src/mdc-knockout-augment';
import {TextfieldTemplate, TextfieldViewModel} from '../../src/mdc-knockout-textfield';
import {MDCTextfield, MDCTextfieldFoundation} from '@material/textfield';

import ko from 'knockout';
augment.registerBindings(ko);
augment.registerComponent(ko, 'mdc-textfield', TextfieldTemplate(), TextfieldViewModel, MDCTextfield, MDCTextfieldFoundation);

suite('textfield component');

test('multiline, fullwidth, and invaid are unwrapped', (done) => {
  const component = bel`
    <mdc-textfield params="
      multiline: multiline,
      fullwidth: fullwidth,
      invalid: invalid
    "></mdc-textfield>`;
  const multiline = ko.observable(true);
  const fullwidth = ko.observable(true);
  const invalid = ko.observable(true);
  ko.applyBindings({multiline: multiline, fullwidth: fullwidth, invalid: invalid}, component);

  setTimeout(() => {
    const wrapper = component.querySelector('.mdc-textfield');
    const initialClasses = wrapper.className;

    multiline(false);
    fullwidth(false);
    invalid(false);

    assert.equal(initialClasses, wrapper.className);

    done();
  });
});

test('textfield with "value" attribute has that value', (done) => {
  const component = bel`<mdc-textfield value="val1"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.equal(input.value, 'val1');

    done();
  });
});

test('"value" binding works', (done) => {
  const component = bel`<mdc-textfield params="value: textfield"></mdc-textfield>`;
  const textfield = ko.observable('');
  ko.applyBindings({textfield: textfield}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.equal(input.value, '');

    textfield('val1');
    assert.equal(input.value, 'val1');

    textfield('val2');
    assert.equal(input.value, 'val2');

    done();
  });
});

test('textfield is disabled when "disabled" attribute present', (done) => {
  const component = bel`<mdc-textfield disabled></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.disabled);

    done();
  });
});

test('textfield is enabled when no "disabled" attribute present', (done) => {
  const component = bel`<mdc-textfield></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isNotOk(input.disabled);

    done();
  });
});

test('"disable" plain param controls disabled state', (done) => {
  const component = bel`<mdc-textfield params="disable: true"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.disabled);

    done();
  });
});

test('"disable" observable param controls disabled state', (done) => {
  const component = bel`<mdc-textfield params="disable: isDisabled"></mdc-textfield>`;
  const isDisabled = ko.observable(false);
  ko.applyBindings({isDisabled: isDisabled}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isNotOk(input.disabled);

    isDisabled(true);
    assert.isOk(input.disabled);

    done();
  });
});

test('"label" plain param sets the label text', (done) => {
  const component = bel`<mdc-textfield params="label: 'text'"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text');

    done();
  });
});

test('"label" observable param sets the label text', (done) => {
  const component = bel`<mdc-textfield params="label: labelText"></mdc-textfield>`;
  const labelText = ko.observable('text1')
  ko.applyBindings({labelText: labelText}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text1');

    labelText('text2');
    assert.equal(label.textContent, 'text2');

    done();
  });
});

test('text node in inner html is treated as label text', (done) => {
  const component = bel`<mdc-textfield>text</mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text');

    done();
  });
});

test('fullwidth textarea renders label as "placeholder" and "aria-label" attributes', (done) => {
  const component = bel`

      <mdc-textfield params="fullwidth: true, label: 'text'"></mdc-textfield>
      <mdc-textfield params="fullwidth: true, label: labelText"></mdc-textfield>
      <mdc-textfield params="fullwidth: true">inner</mdc-textfield>

`;
  const labelText = ko.observable('text1')
  ko.applyBindings({labelText: labelText}, component);

  setTimeout(() => {
    const input1 = component.querySelector('mdc-textfield:nth-child(1) input');
    const input2 = component.querySelector('mdc-textfield:nth-child(2) input');
    const input3 = component.querySelector('mdc-textfield:nth-child(3) input');
    assert.strictEqual(input1.attributes['placeholder'].value, 'text');
    assert.strictEqual(input1.attributes['aria-label'].value, 'text');
    assert.strictEqual(input2.attributes['placeholder'].value, 'text1');
    assert.strictEqual(input2.attributes['aria-label'].value, 'text1');
    assert.strictEqual(input3.attributes['placeholder'].value, 'inner');
    assert.strictEqual(input3.attributes['aria-label'].value, 'inner');

    labelText('text2');
    assert.strictEqual(input2.attributes['placeholder'].value, 'text2');
    assert.strictEqual(input2.attributes['aria-label'].value, 'text2');

    done();
  });
});

test('"help" plain param sets the help text', (done) => {
  const component = bel`<mdc-textfield params="help: 'text'"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text');

    done();
  });
});

test('"help" observable param sets the help text', (done) => {
  const component = bel`<mdc-textfield params="help: helpText"></mdc-textfield>`;
  const helpText = ko.observable('text1')
  ko.applyBindings({helpText: helpText}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text1');

    helpText('text2');
    assert.equal(help.textContent, 'text2');

    done();
  });
});

test('
 node in inner html is treated as help text', (done) => {
  const component = bel`<mdc-textfield><p>text</p></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text');

    done();
  });
});

test('
 node in inner html is treated as persistent help text', (done) => {
  const component = bel`

      <mdc-textfield>
text
</mdc-textfield>
      <mdc-textfield params="help: 'text', persistent: true"></mdc-textfield>

  `;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help1 = component.querySelector('mdc-textfield:nth-child(1) p');
    const help2 = component.querySelector('mdc-textfield:nth-child(2) p');
    assert.equal(help1.className, help2.className);

    done();
  });
});

test('
 node in inner html is treated as help text with validation', (done) => {
  const component = bel`

      <mdc-textfield>
text
</mdc-textfield>
      <mdc-textfield params="help: 'text', validation: true"></mdc-textfield>

  `;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help1 = component.querySelector('mdc-textfield:nth-child(1) p');
    const help2 = component.querySelector('mdc-textfield:nth-child(2) p');
    assert.equal(help1.className, help2.className);

    done();
  });
});

test('not a text or
 node in inner html is ignored', (done) => {
  const component = bel`<mdc-textfield><span id="ignored"></span></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    assert.isNotOk(component.querySelector('#ignored'));

    done();
  });
});

test('if no id was set to the component, it is generated automatically', (done) => {
  const component = bel`<mdc-textfield></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.id.length);

    done();
  });
});

test('"for" attribute of the label element equals to "id" of the input', (done) => {
  const component = bel`<mdc-textfield></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    const label = component.querySelector('label');
    assert.equal(label.htmlFor, input.id);

    done();
  });
});

test('when helptext is present, "input" and "P" elements are connected via "aria-controls" attribute', (done) => {
  const component = bel`<mdc-textfield><p>help</p></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    const help = component.querySelector('p');
    assert.equal(input.attributes['aria-controls'].value, help.id);

    done();
  });
});
<commit_msg>fix(test): Fix typos in textfield component test<commit_after>import {assert} from 'chai';
import bel from 'bel';
import domEvents from 'dom-events';
import augment from '../../src/mdc-knockout-augment';
import {TextfieldTemplate, TextfieldViewModel} from '../../src/mdc-knockout-textfield';
import {MDCTextfield, MDCTextfieldFoundation} from '@material/textfield';

import ko from 'knockout';
augment.registerBindings(ko);
augment.registerComponent(ko, 'mdc-textfield', TextfieldTemplate(), TextfieldViewModel, MDCTextfield, MDCTextfieldFoundation);

suite('textfield component');

test('multiline, fullwidth, and invaid are unwrapped', (done) => {
  const component = bel`
    <mdc-textfield params="
      multiline: multiline,
      fullwidth: fullwidth,
      invalid: invalid
    "></mdc-textfield>`;
  const multiline = ko.observable(true);
  const fullwidth = ko.observable(true);
  const invalid = ko.observable(true);
  ko.applyBindings({multiline: multiline, fullwidth: fullwidth, invalid: invalid}, component);

  setTimeout(() => {
    const wrapper = component.querySelector('.mdc-textfield');
    const initialClasses = wrapper.className;

    multiline(false);
    fullwidth(false);
    invalid(false);

    assert.equal(initialClasses, wrapper.className);

    done();
  });
});

test('textfield with "value" attribute has that value', (done) => {
  const component = bel`<mdc-textfield value="val1"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.equal(input.value, 'val1');

    done();
  });
});

test('"value" binding works', (done) => {
  const component = bel`<mdc-textfield params="value: textfield"></mdc-textfield>`;
  const textfield = ko.observable('');
  ko.applyBindings({textfield: textfield}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.equal(input.value, '');

    textfield('val1');
    assert.equal(input.value, 'val1');

    textfield('val2');
    assert.equal(input.value, 'val2');

    done();
  });
});

test('textfield is disabled when "disabled" attribute present', (done) => {
  const component = bel`<mdc-textfield disabled></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.disabled);

    done();
  });
});

test('textfield is enabled when no "disabled" attribute present', (done) => {
  const component = bel`<mdc-textfield></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isNotOk(input.disabled);

    done();
  });
});

test('"disable" plain param controls disabled state', (done) => {
  const component = bel`<mdc-textfield params="disable: true"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.disabled);

    done();
  });
});

test('"disable" observable param controls disabled state', (done) => {
  const component = bel`<mdc-textfield params="disable: isDisabled"></mdc-textfield>`;
  const isDisabled = ko.observable(false);
  ko.applyBindings({isDisabled: isDisabled}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isNotOk(input.disabled);

    isDisabled(true);
    assert.isOk(input.disabled);

    done();
  });
});

test('"label" plain param sets the label text', (done) => {
  const component = bel`<mdc-textfield params="label: 'text'"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text');

    done();
  });
});

test('"label" observable param sets the label text', (done) => {
  const component = bel`<mdc-textfield params="label: labelText"></mdc-textfield>`;
  const labelText = ko.observable('text1')
  ko.applyBindings({labelText: labelText}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text1');

    labelText('text2');
    assert.equal(label.textContent, 'text2');

    done();
  });
});

test('text node in inner html is treated as label text', (done) => {
  const component = bel`<mdc-textfield>text</mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const label = component.querySelector('label');
    assert.equal(label.textContent, 'text');

    done();
  });
});

test('fullwidth component renders label as "placeholder" and "aria-label" attributes', (done) => {
  const component = bel`

      <mdc-textfield params="fullwidth: true, label: 'text'"></mdc-textfield>
      <mdc-textfield params="fullwidth: true, label: labelText"></mdc-textfield>
      <mdc-textfield params="fullwidth: true">inner</mdc-textfield>

`;
  const labelText = ko.observable('text1')
  ko.applyBindings({labelText: labelText}, component);

  setTimeout(() => {
    const input1 = component.querySelector('mdc-textfield:nth-child(1) input');
    const input2 = component.querySelector('mdc-textfield:nth-child(2) input');
    const input3 = component.querySelector('mdc-textfield:nth-child(3) input');
    assert.strictEqual(input1.attributes['placeholder'].value, 'text');
    assert.strictEqual(input1.attributes['aria-label'].value, 'text');
    assert.strictEqual(input2.attributes['placeholder'].value, 'text1');
    assert.strictEqual(input2.attributes['aria-label'].value, 'text1');
    assert.strictEqual(input3.attributes['placeholder'].value, 'inner');
    assert.strictEqual(input3.attributes['aria-label'].value, 'inner');

    labelText('text2');
    assert.strictEqual(input2.attributes['placeholder'].value, 'text2');
    assert.strictEqual(input2.attributes['aria-label'].value, 'text2');

    done();
  });
});

test('"help" plain param sets the help text', (done) => {
  const component = bel`<mdc-textfield params="help: 'text'"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text');

    done();
  });
});

test('"help" observable param sets the help text', (done) => {
  const component = bel`<mdc-textfield params="help: helpText"></mdc-textfield>`;
  const helpText = ko.observable('text1')
  ko.applyBindings({helpText: helpText}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text1');

    helpText('text2');
    assert.equal(help.textContent, 'text2');

    done();
  });
});

test('
 node in inner html is treated as help text', (done) => {
  const component = bel`<mdc-textfield><p>text</p></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help = component.querySelector('p');
    assert.equal(help.textContent, 'text');

    done();
  });
});

test('
 node in inner html is treated as persistent help text', (done) => {
  const component = bel`

      <mdc-textfield>
text
</mdc-textfield>
      <mdc-textfield params="help: 'text', persistent: true"></mdc-textfield>

  `;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help1 = component.querySelector('mdc-textfield:nth-child(1) p');
    const help2 = component.querySelector('mdc-textfield:nth-child(2) p');
    assert.equal(help1.className, help2.className);

    done();
  });
});

test('
 node in inner html is treated as help text with validation', (done) => {
  const component = bel`

      <mdc-textfield>
text
</mdc-textfield>
      <mdc-textfield params="help: 'text', validation: true"></mdc-textfield>

  `;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const help1 = component.querySelector('mdc-textfield:nth-child(1) p');
    const help2 = component.querySelector('mdc-textfield:nth-child(2) p');
    assert.equal(help1.className, help2.className);

    done();
  });
});

test('not a text or
 node in inner html is ignored', (done) => {
  const component = bel`<mdc-textfield><span id="ignored"></span></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    assert.isNotOk(component.querySelector('#ignored'));

    done();
  });
});

test('if no id was set to the component, it is generated automatically', (done) => {
  const component = bel`<mdc-textfield></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    assert.isOk(input.id.length);

    done();
  });
});

test('"for" attribute of the label element equals to "id" of the input', (done) => {
  const component = bel`<mdc-textfield id="t1"></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    const label = component.querySelector('label');
    assert.equal(label.htmlFor, input.id);

    done();
  });
});

test('when helptext is present, "input" and "P" elements are connected via "aria-controls" attribute', (done) => {
  const component = bel`<mdc-textfield><p>help</p></mdc-textfield>`;
  ko.applyBindings({}, component);

  setTimeout(() => {
    const input = component.querySelector('input');
    const help = component.querySelector('p');
    assert.equal(input.attributes['aria-controls'].value, help.id);

    done();
  });
});
<|endoftext|>


<commit_before>export default class Calendar {
    constructor () {
        this.grid = [];
        this.week = 0;

        let today = new Date();
        this.set(today.getFullYear(), today.getMonth()+1, today.getDate());
    }

    setYear  (y) { this.set(y, this.month, this.date) }
    setMonth (m) { this.set(this.year, m, this.date) }
    setDate  (d) { this.set(this.year, this.month, d) }
    setWeek  (w) { this.week = w }

    get value () {
        return new Date(this.year, this.month-1, this.date);
    }

    set value (d) {
        this.set(d.getFullYear(), d.getMonth()+1, d.getDate());
    }

    set (y, m, d) {
        this.year = y;
        this.month = m;
        this.date = d;

        // Set calendar month to the given month and year. (Month and year in natural units)
        var monthStart = new Date(y, m-1, 1);
        var monthEnd = new Date(y, m, 0);
        var calStart = new Date(y, m-1, 1-monthStart.getDay());
        var calEnd = new Date(y, m, 6-monthEnd.getDay());
        var base = [calStart.getFullYear(), calStart.getMonth()+1, calStart.getDate()];
        var wk = 0, wkDay = 0;

        // Clear previous calendar
        this.grid.length = 0;
        this.grid.push([]);
        this.year = y;
        this.month = m;
        this.date = d;

        // Previous month
        for (var i = 0; i < monthStart.getDay(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + i]);
            wkDay++;
        }

        // Current month
        base = [monthStart.getFullYear(), monthStart.getMonth()+1, monthStart.getDate()];
        for (var i = 0; i < monthEnd.getDate(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + i]);

            // Is this the week?
            if (base[2] + i == d) {
                this.week = wk;
            }

            if (wkDay++ % 7 == 6) {
                this.grid.push([]);
                wk++;
            }
        }

        // Next month
        if (monthEnd.getMonth() == calEnd.getMonth() && monthEnd.getDate() == calEnd.getDate()) {
            // Check empty last row
            if (this.grid[this.grid.length-1].length == 0) {
                this.grid.length -= 1;
            }
            return;
        }

        base = [calEnd.getFullYear(), calEnd.getMonth()+1, 1];
        var ctr = 0;
        for (var i = (monthEnd.getDay() + 1) % 7; i <= calEnd.getDay(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + (ctr++)]);
        }

        // Check empty last row
        if (this.grid[this.grid.length-1].length == 0) {
            this.grid.length -= 1;
        }
    }
}
<commit_msg>Update calendar grid format.<commit_after>export default class Calendar {
    constructor () {
        this.grid = [];     // format, [week] where week is array of [y, m, d, current_month (bool)]
        this.week = 0;

        let today = new Date();
        this.set(today.getFullYear(), today.getMonth()+1, today.getDate());
    }

    setYear  (y) { this.set(y, this.month, this.date) }
    setMonth (m) { this.set(this.year, m, this.date) }
    setDate  (d) { this.set(this.year, this.month, d) }
    setWeek  (w) { this.week = w }

    get value () {
        return new Date(this.year, this.month-1, this.date);
    }

    set value (d) {
        this.set(d.getFullYear(), d.getMonth()+1, d.getDate());
    }

    set (y, m, d) {
        this.year = y;
        this.month = m;
        this.date = d;

        // Set calendar month to the given month and year. (Month and year in natural units)
        var monthStart = new Date(y, m-1, 1);
        var monthEnd = new Date(y, m, 0);
        var calStart = new Date(y, m-1, 1-monthStart.getDay());
        var calEnd = new Date(y, m, 6-monthEnd.getDay());
        var base = [calStart.getFullYear(), calStart.getMonth()+1, calStart.getDate()];
        var wk = 0, wkDay = 0;

        // Clear previous calendar
        this.grid.length = 0;
        this.grid.push([]);
        this.year = y;
        this.month = m;
        this.date = d;

        // Previous month
        for (var i = 0; i < monthStart.getDay(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + i, false]);
            wkDay++;
        }

        // Current month
        base = [monthStart.getFullYear(), monthStart.getMonth()+1, monthStart.getDate()];
        for (var i = 0; i < monthEnd.getDate(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + i, true]);

            // Is this the week?
            if (base[2] + i == d) {
                this.week = wk;
            }

            if (wkDay++ % 7 == 6) {
                this.grid.push([]);
                wk++;
            }
        }

        // Next month
        if (monthEnd.getMonth() == calEnd.getMonth() && monthEnd.getDate() == calEnd.getDate()) {
            // Check empty last row
            if (this.grid[this.grid.length-1].length == 0) {
                this.grid.length -= 1;
            }
            return;
        }

        base = [calEnd.getFullYear(), calEnd.getMonth()+1, 1];
        var ctr = 0;
        for (var i = (monthEnd.getDay() + 1) % 7; i <= calEnd.getDay(); i++) {
            this.grid[wk].push([base[0], base[1], base[2] + (ctr++), false]);
        }

        // Check empty last row
        if (this.grid[this.grid.length-1].length == 0) {
            this.grid.length -= 1;
        }
    }
}
<|endoftext|>


<commit_before>import { types as t } from 'mobx-state-tree'

import { PAGE_SIZE } from '@config'
import { C11N } from '@constant'

import { Community /* PagedCommunities */ } from './Community'

const PagedCommunities = t.model('pagedCommunities', {
  entries: t.optional(t.array(Community), []),
  totalCount: t.optional(t.number, 0),
})

const ContributeRecord = t.model('ContributeRecord', {
  date: t.string,
  count: t.number,
})

const Contributes = t.model('Contributes', {
  records: t.optional(t.array(ContributeRecord), []),
  startDate: t.maybeNull(t.string),
  endDate: t.maybeNull(t.string),
  totalCount: t.maybeNull(t.number),
})

const GithubProfile = t.model('GithubProfile', {
  login: t.string,
  htmlUrl: t.string,
})

export const EduBackground = t.model('EduBackground', {
  school: t.optional(t.string, ''),
  major: t.optional(t.string, ''),
})

export const WorkBackground = t.model('WorkBackground', {
  company: t.optional(t.string, ''),
  title: t.maybeNull(t.string),
})

const SourceContribute = t.model('SourceContribute', {
  web: t.maybeNull(t.boolean),
  server: t.maybeNull(t.boolean),
  mobile: t.maybeNull(t.boolean),
  weApp: t.maybeNull(t.boolean),
  h5: t.maybeNull(t.boolean),
})

export const Achievement = t.model('Achievement', {
  reputation: t.optional(t.number, 0),
  contentsStaredCount: t.optional(t.number, 0),
  contentsFavoritedCount: t.optional(t.number, 0),
  sourceContribute: t.optional(SourceContribute, {
    web: false,
    server: false,
    mobile: false,
    weApp: false,
    h5: false,
  }),
  donateMember: t.optional(t.boolean, false),
  seniorMember: t.optional(t.boolean, false),
  sponsorMember: t.optional(t.boolean, false),
})

const Customization = t.model('Customization', {
  bannerLayout: t.optional(
    t.enumeration('contentsLayout', [C11N.DIGEST, C11N.BRIEF]),
    C11N.DIGEST
  ),
  contentsLayout: t.optional(
    t.enumeration('contentsLayout', [C11N.DIGEST, C11N.LIST]),
    C11N.DIGEST
  ),
  contentDivider: t.optional(t.boolean, false),
  contentHover: t.optional(t.boolean, true),
  markViewed: t.optional(t.boolean, true),
  displayDensity: t.optional(
    t.enumeration('displayDensity', ['20', '25', '30']),
    '20'
  ),
  // theme
  // ...
})

const UserSocial = t.model('UserSocial', {
  qq: t.maybeNull(t.string),
  weibo: t.maybeNull(t.string),
  weichat: t.maybeNull(t.string),
  github: t.maybeNull(t.string),
  zhihu: t.maybeNull(t.string),
  douban: t.maybeNull(t.string),
  twitter: t.maybeNull(t.string),
  facebook: t.maybeNull(t.string),
  dribble: t.maybeNull(t.string),
  instagram: t.maybeNull(t.string),
  pinterest: t.maybeNull(t.string),
  huaban: t.maybeNull(t.string),
})

export const User = t.model('User', {
  // identifier is desiged to be immutable, this id would be updated when login
  /* id: t.optional(t.string, ''), */
  id: t.maybeNull(t.string),
  login: t.maybeNull(t.string),
  nickname: t.maybeNull(t.string),
  bio: t.maybeNull(t.string),
  avatar: t.maybeNull(t.string),
  views: t.optional(t.number, 0),
  email: t.maybeNull(t.string),
  location: t.maybeNull(t.string),
  geoCity: t.maybeNull(t.string),
  // TODO: backgrounds
  educationBackgrounds: t.optional(t.array(EduBackground), []),
  workBackgrounds: t.optional(t.array(WorkBackground), []),
  sex: t.maybeNull(t.string),
  // social
  social: t.optional(UserSocial, {}),
  fromGithub: t.optional(t.boolean, false),
  /* fromWeixin: t.optional(t.boolean, false), */
  /* subscribedCommunities: t.optional(pagedCommunities, {}), */
  subscribedCommunities: t.maybeNull(PagedCommunities),
  subscribedCommunitiesCount: t.optional(t.number, 0),
  contributes: t.optional(Contributes, {}),
  githubProfile: t.maybeNull(GithubProfile),
  // cmsPassportString: t.optional(t.string, '{}'),

  followingsCount: t.optional(t.number, 0),
  followersCount: t.optional(t.number, 0),

  achievement: t.maybeNull(Achievement),
  editableCommunities: t.maybeNull(PagedCommunities),

  insertedAt: t.optional(t.string, ''),
  updatedAt: t.optional(t.string, ''),

  viewerHasFollowed: t.optional(t.boolean, false),
  customization: t.optional(Customization, {}),
})

export const SimpleUser = t.model('SimpleUser2', {
  id: t.maybeNull(t.string),
  login: t.maybeNull(t.string),
  nickname: t.maybeNull(t.string),
  bio: t.maybeNull(t.string),
  avatar: t.maybeNull(t.string),
})

export const EmptyUser = {
  id: '',
  nickname: '',
  login: '',
  bio: '',
  avatar: '',
  fromGithub: false,
  fromWeixin: false,
  subscribedCommunities: {},
  contributes: {},
  githubProfile: null,
  // cmsPassportString: '{}',
  ...EmptyAchievement,
}

export const EmptyAchievement = {
  achievement: {
    reputation: 0,
    contentsStaredCount: 0,
    contentsFavoritedCount: 0,
    donateMember: false,
    seniorMember: false,
    sponsorMember: false,
  },
}

export const PagedUsers = t.model('PagedUsers', {
  entries: t.optional(t.array(User), []),
  pageNumber: t.optional(t.number, 1),
  pageSize: t.optional(t.number, PAGE_SIZE.D),
  totalCount: t.optional(t.number, 0),
  totalPages: t.optional(t.number, 0),
})
<commit_msg>fix(travis): try to solve referenceError of EmptyAchievement<commit_after>import { types as t } from 'mobx-state-tree'

import { PAGE_SIZE } from '@config'
import { C11N } from '@constant'

import { Community /* PagedCommunities */ } from './Community'

const PagedCommunities = t.model('pagedCommunities', {
  entries: t.optional(t.array(Community), []),
  totalCount: t.optional(t.number, 0),
})

const ContributeRecord = t.model('ContributeRecord', {
  date: t.string,
  count: t.number,
})

const Contributes = t.model('Contributes', {
  records: t.optional(t.array(ContributeRecord), []),
  startDate: t.maybeNull(t.string),
  endDate: t.maybeNull(t.string),
  totalCount: t.maybeNull(t.number),
})

const GithubProfile = t.model('GithubProfile', {
  login: t.string,
  htmlUrl: t.string,
})

export const EduBackground = t.model('EduBackground', {
  school: t.optional(t.string, ''),
  major: t.optional(t.string, ''),
})

export const WorkBackground = t.model('WorkBackground', {
  company: t.optional(t.string, ''),
  title: t.maybeNull(t.string),
})

const SourceContribute = t.model('SourceContribute', {
  web: t.maybeNull(t.boolean),
  server: t.maybeNull(t.boolean),
  mobile: t.maybeNull(t.boolean),
  weApp: t.maybeNull(t.boolean),
  h5: t.maybeNull(t.boolean),
})

export const Achievement = t.model('Achievement', {
  reputation: t.optional(t.number, 0),
  contentsStaredCount: t.optional(t.number, 0),
  contentsFavoritedCount: t.optional(t.number, 0),
  sourceContribute: t.optional(SourceContribute, {
    web: false,
    server: false,
    mobile: false,
    weApp: false,
    h5: false,
  }),
  donateMember: t.optional(t.boolean, false),
  seniorMember: t.optional(t.boolean, false),
  sponsorMember: t.optional(t.boolean, false),
})

const Customization = t.model('Customization', {
  bannerLayout: t.optional(
    t.enumeration('contentsLayout', [C11N.DIGEST, C11N.BRIEF]),
    C11N.DIGEST
  ),
  contentsLayout: t.optional(
    t.enumeration('contentsLayout', [C11N.DIGEST, C11N.LIST]),
    C11N.DIGEST
  ),
  contentDivider: t.optional(t.boolean, false),
  contentHover: t.optional(t.boolean, true),
  markViewed: t.optional(t.boolean, true),
  displayDensity: t.optional(
    t.enumeration('displayDensity', ['20', '25', '30']),
    '20'
  ),
  // theme
  // ...
})

const UserSocial = t.model('UserSocial', {
  qq: t.maybeNull(t.string),
  weibo: t.maybeNull(t.string),
  weichat: t.maybeNull(t.string),
  github: t.maybeNull(t.string),
  zhihu: t.maybeNull(t.string),
  douban: t.maybeNull(t.string),
  twitter: t.maybeNull(t.string),
  facebook: t.maybeNull(t.string),
  dribble: t.maybeNull(t.string),
  instagram: t.maybeNull(t.string),
  pinterest: t.maybeNull(t.string),
  huaban: t.maybeNull(t.string),
})

export const User = t.model('User', {
  // identifier is desiged to be immutable, this id would be updated when login
  /* id: t.optional(t.string, ''), */
  id: t.maybeNull(t.string),
  login: t.maybeNull(t.string),
  nickname: t.maybeNull(t.string),
  bio: t.maybeNull(t.string),
  avatar: t.maybeNull(t.string),
  views: t.optional(t.number, 0),
  email: t.maybeNull(t.string),
  location: t.maybeNull(t.string),
  geoCity: t.maybeNull(t.string),
  // TODO: backgrounds
  educationBackgrounds: t.optional(t.array(EduBackground), []),
  workBackgrounds: t.optional(t.array(WorkBackground), []),
  sex: t.maybeNull(t.string),
  // social
  social: t.optional(UserSocial, {}),
  fromGithub: t.optional(t.boolean, false),
  /* fromWeixin: t.optional(t.boolean, false), */
  /* subscribedCommunities: t.optional(pagedCommunities, {}), */
  subscribedCommunities: t.maybeNull(PagedCommunities),
  subscribedCommunitiesCount: t.optional(t.number, 0),
  contributes: t.optional(Contributes, {}),
  githubProfile: t.maybeNull(GithubProfile),
  // cmsPassportString: t.optional(t.string, '{}'),

  followingsCount: t.optional(t.number, 0),
  followersCount: t.optional(t.number, 0),

  achievement: t.maybeNull(Achievement),
  editableCommunities: t.maybeNull(PagedCommunities),

  insertedAt: t.optional(t.string, ''),
  updatedAt: t.optional(t.string, ''),

  viewerHasFollowed: t.optional(t.boolean, false),
  customization: t.optional(Customization, {}),
})

export const SimpleUser = t.model('SimpleUser2', {
  id: t.maybeNull(t.string),
  login: t.maybeNull(t.string),
  nickname: t.maybeNull(t.string),
  bio: t.maybeNull(t.string),
  avatar: t.maybeNull(t.string),
})

export const EmptyAchievement = {
  achievement: {
    reputation: 0,
    contentsStaredCount: 0,
    contentsFavoritedCount: 0,
    donateMember: false,
    seniorMember: false,
    sponsorMember: false,
  },
}

export const EmptyUser = {
  id: '',
  nickname: '',
  login: '',
  bio: '',
  avatar: '',
  fromGithub: false,
  fromWeixin: false,
  subscribedCommunities: {},
  contributes: {},
  githubProfile: null,
  // cmsPassportString: '{}',
  ...EmptyAchievement,
}

export const PagedUsers = t.model('PagedUsers', {
  entries: t.optional(t.array(User), []),
  pageNumber: t.optional(t.number, 1),
  pageSize: t.optional(t.number, PAGE_SIZE.D),
  totalCount: t.optional(t.number, 0),
  totalPages: t.optional(t.number, 0),
})
<|endoftext|>


<commit_before>  if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep", "../deep-stores"], function (require, deep) {

    return function(deep){
  //_____________________________________________________________________ COLLECTION STORE
        /**
         * A store based on simple array
         * @class deep.store.Collection
         * @constructor
         * @param {Array} arr a first array of objects to hold
         * @param {Object} options could contain 'schema'
         */
        deep.store.Collection = deep.compose.Classes(deep.Store,
        function (protocole, collection, schema, options) {
            if (collection)
                this.collection = collection;
            if(schema)
                this.schema = schema;
            if(options)
                deep.utils.up(options, this);
        },
        {
            /**
             * @method init
             */
            init: deep.compose.after(function () {
                var self = this;
                //console.log("deep.store.Collection.init : this.collection : ", this.collection, " - this.schema : ", this.schema);
                this.collection = this.collection || [];
                if (typeof this.collection === 'string' || typeof this.schema === 'string')
                    return deep(this)
                        .query("./[collection,schema]")
                        .load()
                        .done(function(success){
                             return self;
                        });
            }),
            /**
             * @method get
             * @param  {String} id the id of the object to retrieve. Could also be a (deep)query.
             * @param {Object} options an options object (here there is no options)
             * @return {Object} the retrieved object
             */
            get: function (id, options) {
                options = options || {};
                //console.log("deep.store.Collection.get : ",id," - stock : ", this.collection)
                var q = "";
                var queried = false;
                if(!id)
                {
                    q = "./*";
                    queried = true;
                }
                else if (id[0] == "*")
                {
                    q = "./"+id;
                    queried = true;
                }
                else if(id[0] == "?")
                {
                    q = "./*"+id;
                    queried = true;
                }
                else
                    q = "./*?id=" + id;
                //console.log("deep.store.Collection.get : q :",q);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var r = deep.query(col, q);
                //console.log("deep.store.Collection.get : res :",r);
                if (!queried && r instanceof Array)
                    r = r.shift();
                if(typeof r === 'undefined')
                    return deep.when(deep.errors.NotFound());
                return deep.when(r);
            },
            /**
             * @method put
             * @param  {Object} object the object to update
             * @param  {Object} options an options object : could contain 'id'
             * @return {Object} the updated object
             */
            put: function (object, options) {
                options = options || {};
                var id = options.id || object.id;
                if (!id)
                    return deep.when(deep.errors.Store("Collection store need id on put"));

                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();

                var r = deep.query(col, "./*?id=" + id, { resultType: "full" });
                if (!r || r.length === 0)
                    return deep.when(deep.errors.NotFound("no items found in collection with : " + id));
                r = r.shift();
                if(options.query)
                {
                    r.value = deep.utils.copy(r.value);
                    deep.utils.replace(r.value, options.query, object);
                }
                else
                {
                    if(!object.id)
                        object.id = options.id;
                    r.value = object;
                }

                var schema = this.schema;
                if(schema)
                {
                    if(schema._deep_ocm_)
                        schema = schema("put");
                    var report = deep.validate(r.value, schema);
                    if(!report.valid)
                        return deep.when(deep.errors.PreconditionFail(report));
                }

                if (r.ancestor)
                    r.ancestor.value[r.key] = r.value;
                return deep.when(r.value);
            },
            /**
             * @method post
             * @param  {Object} object
             * @param  {Object} options (optional)
             * @return {Object} the inserted object (decorated with it's id)
             */
            post: function (object, options) {
                //console.log("deep.store.Collection.post : ", object, options);
                options = options || {};
                options.id = options.id || object.id;
                if (!options.id)
                    object.id = options.id = "id"+new Date().valueOf(); // mongo styled id
                if(!object.id)
                    object.id = options.id;
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var res = deep.query(col, "./*?id=" + object.id);
                if (res && res.length > 0)
                    return deep.when(deep.errors.Conflict("deep.store.Collection.post : An object has the same id before post : please put in place : object : ", object));
                col.push(object);
                return deep.when(object);
            },
            /**
             * @method del
             * @param  {String} id
             * @param  {Object} options no options for the moment
             * @return {Object} the removed object
             */
            del: function (id, options) {
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var removed = deep(col).remove("./*?id=" + id).done();
                if (removed)
                    removed = removed.shift();
                return deep.when(removed);
            },
            /**
             * @method patch
             * @param  {Object} object  the update to apply to object
             * @param  {Object} options  could contain 'id'
             * @return {deep.Chain} a chain that hold the patched object and has injected values as success object.
             */

            /**
             * select a range in collection
             * @method range
             * @param  {Number} start
             * @param  {Number} end
             * @return {deep.Chain} a chain that hold the selected range and has injected values as success object.
             */
            range: function (start, end, query) {
                //console.log("deep.store.Collection.range : ", start, end);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                query = query || "";
                query += "&limit("+((end-start)+1)+","+start+")";
                var res = deep.query(col, "./*?"+query);
                return deep.utils.createRangeObject(start, end, this.collection.length, res.length, res, query);
            },
            flush:function(){
                this.collection = [];
            }
        });

        deep.store.Collection.create = function(protocole, collection, schema, options)
        {
            return new deep.store.Collection(protocole, collection, schema, options);
        };
        deep.utils.sheet(deep.store.ObjectSheet, deep.store.Collection.prototype);

        return deep.store.Collection;
    };
});
<commit_msg>do  copy on Collection.get<commit_after>  if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep", "../deep-stores"], function (require, deep) {

    return function(deep){
  //_____________________________________________________________________ COLLECTION STORE
        /**
         * A store based on simple array
         * @class deep.store.Collection
         * @constructor
         * @param {Array} arr a first array of objects to hold
         * @param {Object} options could contain 'schema'
         */
        deep.store.Collection = deep.compose.Classes(deep.Store,
        function (protocole, collection, schema, options) {
            if (collection)
                this.collection = collection;
            if(schema)
                this.schema = schema;
            if(options)
                deep.utils.up(options, this);
        },
        {
            /**
             * @method init
             */
            init: deep.compose.after(function () {
                var self = this;
                //console.log("deep.store.Collection.init : this.collection : ", this.collection, " - this.schema : ", this.schema);
                this.collection = this.collection || [];
                if (typeof this.collection === 'string' || typeof this.schema === 'string')
                    return deep(this)
                        .query("./[collection,schema]")
                        .load()
                        .done(function(success){
                             return self;
                        });
            }),
            /**
             * @method get
             * @param  {String} id the id of the object to retrieve. Could also be a (deep)query.
             * @param {Object} options an options object (here there is no options)
             * @return {Object} the retrieved object
             */
            get: function (id, options) {
                options = options || {};
                //console.log("deep.store.Collection.get : ",id," - stock : ", this.collection)
                var q = "";
                var queried = false;
                if(!id)
                {
                    q = "./*";
                    queried = true;
                }
                else if (id[0] == "*")
                {
                    q = "./"+id;
                    queried = true;
                }
                else if(id[0] == "?")
                {
                    q = "./*"+id;
                    queried = true;
                }
                else
                    q = "./*?id=" + id;
                //console.log("deep.store.Collection.get : q :",q);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var r = deep.query(col, q);
                //console.log("deep.store.Collection.get : res :",r);
                if (!queried && r instanceof Array)
                    r = r.shift();
                if(typeof r === 'undefined')
                    return deep.when(deep.errors.NotFound());

                return deep.when(deep.utils.copy(r));
            },
            /**
             * @method put
             * @param  {Object} object the object to update
             * @param  {Object} options an options object : could contain 'id'
             * @return {Object} the updated object
             */
            put: function (object, options) {
                options = options || {};
                var id = options.id || object.id;
                if (!id)
                    return deep.when(deep.errors.Store("Collection store need id on put"));

                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();

                var r = deep.query(col, "./*?id=" + id, { resultType: "full" });
                if (!r || r.length === 0)
                    return deep.when(deep.errors.NotFound("no items found in collection with : " + id));
                r = r.shift();
                if(options.query)
                {
                    r.value = deep.utils.copy(r.value);
                    deep.utils.replace(r.value, options.query, object);
                }
                else
                {
                    if(!object.id)
                        object.id = options.id;
                    r.value = object;
                }

                var schema = this.schema;
                if(schema)
                {
                    if(schema._deep_ocm_)
                        schema = schema("put");
                    var report = deep.validate(r.value, schema);
                    if(!report.valid)
                        return deep.when(deep.errors.PreconditionFail(report));
                }

                if (r.ancestor)
                    r.ancestor.value[r.key] = r.value;
                return deep.when(r.value);
            },
            /**
             * @method post
             * @param  {Object} object
             * @param  {Object} options (optional)
             * @return {Object} the inserted object (decorated with it's id)
             */
            post: function (object, options) {
                //console.log("deep.store.Collection.post : ", object, options);
                options = options || {};
                options.id = options.id || object.id;
                if (!options.id)
                    object.id = options.id = "id"+new Date().valueOf(); // mongo styled id
                if(!object.id)
                    object.id = options.id;
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var res = deep.query(col, "./*?id=" + object.id);
                if (res && res.length > 0)
                    return deep.when(deep.errors.Conflict("deep.store.Collection.post : An object has the same id before post : please put in place : object : ", object));
                col.push(object);
                return deep.when(object);
            },
            /**
             * @method del
             * @param  {String} id
             * @param  {Object} options no options for the moment
             * @return {Object} the removed object
             */
            del: function (id, options) {
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                var removed = deep.utils.remove(col, "./*?id=" + id);
                if (removed)
                    removed = removed.shift();
                return deep.when(removed);
            },
            /**
             * @method patch
             * @param  {Object} object  the update to apply to object
             * @param  {Object} options  could contain 'id'
             * @return {deep.Chain} a chain that hold the patched object and has injected values as success object.
             */

            /**
             * select a range in collection
             * @method range
             * @param  {Number} start
             * @param  {Number} end
             * @return {deep.Chain} a chain that hold the selected range and has injected values as success object.
             */
            range: function (start, end, query) {
                //console.log("deep.store.Collection.range : ", start, end);
                var col = this.collection;
                if(this.collection._deep_ocm_)
                    col = this.collection();
                query = query || "";
                query += "&limit("+((end-start)+1)+","+start+")";
                var res = deep.query(col, "./*?"+query);
                return deep.utils.createRangeObject(start, end, this.collection.length, res.length, res, query);
            },
            flush:function(){
                this.collection = [];
            }
        });

        deep.store.Collection.create = function(protocole, collection, schema, options)
        {
            return new deep.store.Collection(protocole, collection, schema, options);
        };
        deep.utils.sheet(deep.store.ObjectSheet, deep.store.Collection.prototype);

        return deep.store.Collection;
    };
});
<|endoftext|>