<commit_before>'use strict';
import fs from 'fs';
import path from 'path';

import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import SystemBellPlugin from 'system-bell-webpack-plugin';
import Clean from 'clean-webpack-plugin';
import merge from 'webpack-merge';
import React from 'react';
import ReactDOM from 'react-dom/server';
import MTRC from 'markdown-to-react-components';

import App from './demo/App.jsx';
import pkg from './package.json';

const TARGET = process.env.npm_lifecycle_event;
const ROOT_PATH = path.resolve(__dirname);
const config = {
  paths: {
    dist: path.join(ROOT_PATH, 'dist'),
    src: path.join(ROOT_PATH, 'src'),
    demo: path.join(ROOT_PATH, 'demo'),
    tests: path.join(ROOT_PATH, 'tests')
  },
  filename: 'boilerplate',
  library: 'Boilerplate'
};
const CSS_PATHS = [
  config.paths.demo,
  path.join(ROOT_PATH, 'style.css'),
  path.join(ROOT_PATH, 'node_modules/purecss'),
  path.join(ROOT_PATH, 'node_modules/highlight.js/styles/github.css'),
  path.join(ROOT_PATH, 'node_modules/react-ghfork/gh-fork-ribbon.ie.css'),
  path.join(ROOT_PATH, 'node_modules/react-ghfork/gh-fork-ribbon.css')
];

process.env.BABEL_ENV = TARGET;

const demoCommon = {
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.png', '.jpg']
  },
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: ['eslint'],
        include: [
          config.paths.demo,
          config.paths.src
        ]
      }
    ],
    loaders: [
      {
        test: /\.png$/,
        loader: 'url?limit=100000&mimetype=image/png',
        include: config.paths.demo
      },
      {
        test: /\.jpg$/,
        loader: 'file',
        include: config.paths.demo
      },
      {
        test: /\.json$/,
        loader: 'json',
        include: path.join(ROOT_PATH, 'package.json')
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'start') {
  module.exports = merge(demoCommon, {
    devtool: 'eval-source-map',
    entry: config.paths.demo,
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify('development')
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        templateContent: renderJSX
      }),
      new webpack.HotModuleReplacementPlugin()
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loaders: ['style', 'css'],
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    },
    devServer: {
      historyApiFallback: true,
      hot: true,
      inline: true,
      progress: true,
      host: process.env.HOST,
      port: process.env.PORT,
      stats: 'errors-only'
    }
  });
}

if (TARGET === 'gh-pages' || TARGET === 'deploy-gh-pages') {
  module.exports = merge(demoCommon, {
    entry: {
      app: config.paths.demo,
      vendors: [
        'react'
      ]
    },
    output: {
      path: './gh-pages',
      filename: 'bundle.[chunkhash].js'
    },
    plugins: [
      new Clean(['gh-pages']),
      new ExtractTextPlugin('styles.[chunkhash].css'),
      new webpack.DefinePlugin({
          // This has effect on the react lib size
        'process.env.NODE_ENV': JSON.stringify('production')
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        templateContent: renderJSX.bind(null, ReactDOM.renderToString(<App />))
      }),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      }),
      new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.[chunkhash].js')
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract('style', 'css'),
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    }
  });
}

// !TARGET === prepush hook for test
if (TARGET === 'test' || TARGET === 'tdd' || !TARGET) {
  module.exports = merge(demoCommon, {
    module: {
      preLoaders: [
        {
          test: /\.jsx?$/,
          loaders: ['eslint'],
          include: [
            config.paths.tests
          ]
        }
      ],
      loaders: [
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.src,
            config.paths.tests
          ]
        }
      ]
    }
  })
}

const distCommon = {
  devtool: 'source-map',
  output: {
    path: config.paths.dist,
    libraryTarget: 'umd',
    library: config.library
  },
  entry: config.paths.src,
  externals: {
    'react': {
        commonjs: 'react',
        commonjs2: 'react',
        amd: 'React',
        root: 'React'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loaders: ['babel'],
        include: config.paths.src
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'dist') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.js'
    }
  });
}

if (TARGET === 'dist-min') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.min.js'
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]
  });
}

function renderJSX(demoTemplate, templateParams, compilation) {
  demoTemplate = demoTemplate || '';

  var tpl = fs.readFileSync(path.join(__dirname, 'lib/index_template.tpl'), 'utf8');
  var readme = fs.readFileSync(path.join(__dirname, 'README.md'), 'utf8');
  var replacements = {
    name: pkg.name,
    description: pkg.description,
    demo: demoTemplate,
    documentation: ReactDOM.renderToStaticMarkup(

{MTRC(readme).tree}

    )
  };

  return tpl.replace(/%(\w*)%/g, function(match) {
    var key = match.slice(1, -1);

    return replacements[key] ? replacements[key] : match;
  });
}
<commit_msg>Point directly to __dirname at ROOT_PATH<commit_after>'use strict';
import fs from 'fs';
import path from 'path';

import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import SystemBellPlugin from 'system-bell-webpack-plugin';
import Clean from 'clean-webpack-plugin';
import merge from 'webpack-merge';
import React from 'react';
import ReactDOM from 'react-dom/server';
import MTRC from 'markdown-to-react-components';

import App from './demo/App.jsx';
import pkg from './package.json';

const TARGET = process.env.npm_lifecycle_event;
const ROOT_PATH = __dirname;
const config = {
  paths: {
    dist: path.join(ROOT_PATH, 'dist'),
    src: path.join(ROOT_PATH, 'src'),
    demo: path.join(ROOT_PATH, 'demo'),
    tests: path.join(ROOT_PATH, 'tests')
  },
  filename: 'boilerplate',
  library: 'Boilerplate'
};
const CSS_PATHS = [
  config.paths.demo,
  path.join(ROOT_PATH, 'style.css'),
  path.join(ROOT_PATH, 'node_modules/purecss'),
  path.join(ROOT_PATH, 'node_modules/highlight.js/styles/github.css'),
  path.join(ROOT_PATH, 'node_modules/react-ghfork/gh-fork-ribbon.ie.css'),
  path.join(ROOT_PATH, 'node_modules/react-ghfork/gh-fork-ribbon.css')
];

process.env.BABEL_ENV = TARGET;

const demoCommon = {
  resolve: {
    extensions: ['', '.js', '.jsx', '.css', '.png', '.jpg']
  },
  module: {
    preLoaders: [
      {
        test: /\.jsx?$/,
        loaders: ['eslint'],
        include: [
          config.paths.demo,
          config.paths.src
        ]
      }
    ],
    loaders: [
      {
        test: /\.png$/,
        loader: 'url?limit=100000&mimetype=image/png',
        include: config.paths.demo
      },
      {
        test: /\.jpg$/,
        loader: 'file',
        include: config.paths.demo
      },
      {
        test: /\.json$/,
        loader: 'json',
        include: path.join(ROOT_PATH, 'package.json')
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'start') {
  module.exports = merge(demoCommon, {
    devtool: 'eval-source-map',
    entry: config.paths.demo,
    plugins: [
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify('development')
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        templateContent: renderJSX
      }),
      new webpack.HotModuleReplacementPlugin()
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loaders: ['style', 'css'],
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    },
    devServer: {
      historyApiFallback: true,
      hot: true,
      inline: true,
      progress: true,
      host: process.env.HOST,
      port: process.env.PORT,
      stats: 'errors-only'
    }
  });
}

if (TARGET === 'gh-pages' || TARGET === 'deploy-gh-pages') {
  module.exports = merge(demoCommon, {
    entry: {
      app: config.paths.demo,
      vendors: [
        'react'
      ]
    },
    output: {
      path: './gh-pages',
      filename: 'bundle.[chunkhash].js'
    },
    plugins: [
      new Clean(['gh-pages']),
      new ExtractTextPlugin('styles.[chunkhash].css'),
      new webpack.DefinePlugin({
          // This has effect on the react lib size
        'process.env.NODE_ENV': JSON.stringify('production')
      }),
      new HtmlWebpackPlugin({
        title: pkg.name + ' - ' + pkg.description,
        templateContent: renderJSX.bind(null, ReactDOM.renderToString(<App />))
      }),
      new webpack.optimize.DedupePlugin(),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      }),
      new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.[chunkhash].js')
    ],
    module: {
      loaders: [
        {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract('style', 'css'),
          include: CSS_PATHS
        },
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.demo,
            config.paths.src
          ]
        }
      ]
    }
  });
}

// !TARGET === prepush hook for test
if (TARGET === 'test' || TARGET === 'tdd' || !TARGET) {
  module.exports = merge(demoCommon, {
    module: {
      preLoaders: [
        {
          test: /\.jsx?$/,
          loaders: ['eslint'],
          include: [
            config.paths.tests
          ]
        }
      ],
      loaders: [
        {
          test: /\.jsx?$/,
          loaders: ['babel'],
          include: [
            config.paths.src,
            config.paths.tests
          ]
        }
      ]
    }
  })
}

const distCommon = {
  devtool: 'source-map',
  output: {
    path: config.paths.dist,
    libraryTarget: 'umd',
    library: config.library
  },
  entry: config.paths.src,
  externals: {
    'react': {
        commonjs: 'react',
        commonjs2: 'react',
        amd: 'React',
        root: 'React'
    }
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loaders: ['babel'],
        include: config.paths.src
      }
    ]
  },
  plugins: [
    new SystemBellPlugin()
  ]
};

if (TARGET === 'dist') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.js'
    }
  });
}

if (TARGET === 'dist-min') {
  module.exports = merge(distCommon, {
    output: {
      filename: config.filename + '.min.js'
    },
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          warnings: false
        }
      })
    ]
  });
}

function renderJSX(demoTemplate, templateParams, compilation) {
  demoTemplate = demoTemplate || '';

  var tpl = fs.readFileSync(path.join(__dirname, 'lib/index_template.tpl'), 'utf8');
  var readme = fs.readFileSync(path.join(__dirname, 'README.md'), 'utf8');
  var replacements = {
    name: pkg.name,
    description: pkg.description,
    demo: demoTemplate,
    documentation: ReactDOM.renderToStaticMarkup(

{MTRC(readme).tree}

    )
  };

  return tpl.replace(/%(\w*)%/g, function(match) {
    var key = match.slice(1, -1);

    return replacements[key] ? replacements[key] : match;
  });
}
<|endoftext|>


<commit_before>import path        from "path"
import webpack     from "webpack"
import HTMLPlugin  from 'html-webpack-plugin'
import { APP_STAGES } from "./src/constants/App"

let plugins = [];

const config = {
  mode: "development",
  entry: {
    app: ['babel-polyfill', path.join(__dirname, "src/index.js")],
    businesscard_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/businesscard/index.js")],
    map_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/map/index.js")],
    mapAndEntryList_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/mapAndEntryList/index.js")]
  },
  output: {
    path: path.join(__dirname, 'dist/'),
    filename: "[name].js"
  },
  devServer: {
    hot: true,
    inline: true,
    proxy: {
      "/api": {
        target: "http://localhost:6767",
        pathRewrite: {"^/api" : ""}
      }
    }
  },
  target: "web",
  cache: true,
  watch: false,
  module: {
    rules: [
      {
        test:   /\.jsx?$/,
        loader: "babel-loader",
        query: {
          plugins: ['transform-decorators-legacy']
        },
        include: [
          path.resolve(__dirname, "src"),
          path.resolve(__dirname, "spec"),
          path.resolve(__dirname, "node_modules/vm-leaflet-icons")
        ],
      },
      {
        test:   /\.css$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: 'global' // required because of reapop-theme-wybo@1.0.2
            }
          }
        ]
      },
      {
        test:   /\.jpe?g$|\.gif$|\.png$/,
        loader: "url-loader?limit=10000"
      },
      {
        test: /\.woff(2)?(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff"
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=application/octet-stream"
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: "file-loader"
      },
      {
        test: /\.otf$/,
        loader: 'url-loader?limit=10000&mimetype=application/font-otf'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=image/svg+xml"
      }
    ]
  },
  resolve: {
    extensions: [".jsx", ".js"],
    alias: {
      // This is a quick fix:
      // Without pointing to the minified leaflet file
      // webpack includes 'leaflet-src.js'
      leaflet$: path.resolve(__dirname, "node_modules/leaflet/dist/leaflet.js")
    }
  }
};

let htmlPluginOptions = {
  template : "./src/index.html",
  title    : "Karte von morgen",
  favicon  : "./src/img/favicon.ico",
  inject   : 'body',
  pack_for_nightly : (process.env.NODE_ENV === APP_STAGES.NIGHTLY)
};

switch (process.env.NODE_ENV) {
  case APP_STAGES.LOCAL:
    plugins.push(new webpack.DefinePlugin({
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.LOCAL)
    }));
   plugins.push(new webpack.HotModuleReplacementPlugin());
   break;

  case APP_STAGES.NIGHTLY:
    htmlPluginOptions.minify = {
      removeComments        : true,
      collapseWhitespace    : true,
      conservativeCollapse  : false,
      minifyJS              : true,
      minifyCSS             : true,
    };

    // Enable React optimizations.
    plugins.push(new webpack.DefinePlugin({
      'process.env.STAGE'     : JSON.stringify('nightly'),
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.NIGHTLY)
    }));
    break;

  default:
    // production
    htmlPluginOptions.minify = {
      removeComments        : true,
      collapseWhitespace    : true,
      conservativeCollapse  : false,
      minifyJS              : true,
      minifyCSS             : true,
    };

    // Enable React optimizations.
    plugins.push(new webpack.DefinePlugin({
      'process.env.STAGE'     : JSON.stringify('production'),
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.PRODUCTION)
    }));
}

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "index.html",
  chunks: ["app"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "businesscard.html",
  chunks: ["businesscard_widget"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "map.html",
  chunks: ["map_widget"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "mapAndEntryList.html",
  chunks: ["mapAndEntryList_widget"]
}));

config.plugins = plugins;
module.exports = config;
<commit_msg>Fix the proxy pathRewrite rules for using a local OFDB server<commit_after>import path        from "path"
import webpack     from "webpack"
import HTMLPlugin  from 'html-webpack-plugin'
import { APP_STAGES } from "./src/constants/App"

let plugins = [];

const config = {
  mode: "development",
  entry: {
    app: ['babel-polyfill', path.join(__dirname, "src/index.js")],
    businesscard_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/businesscard/index.js")],
    map_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/map/index.js")],
    mapAndEntryList_widget: ['babel-polyfill', path.join(__dirname, "src/widgets/mapAndEntryList/index.js")]
  },
  output: {
    path: path.join(__dirname, 'dist/'),
    filename: "[name].js"
  },
  devServer: {
    hot: true,
    inline: true,
    proxy: {
      "/api/v0": {
        target: "http://localhost:6767",
        pathRewrite: {"^/api/v0" : "/api"}
      }
    }
  },
  target: "web",
  cache: true,
  watch: false,
  module: {
    rules: [
      {
        test:   /\.jsx?$/,
        loader: "babel-loader",
        query: {
          plugins: ['transform-decorators-legacy']
        },
        include: [
          path.resolve(__dirname, "src"),
          path.resolve(__dirname, "spec"),
          path.resolve(__dirname, "node_modules/vm-leaflet-icons")
        ],
      },
      {
        test:   /\.css$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: 'global' // required because of reapop-theme-wybo@1.0.2
            }
          }
        ]
      },
      {
        test:   /\.jpe?g$|\.gif$|\.png$/,
        loader: "url-loader?limit=10000"
      },
      {
        test: /\.woff(2)?(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=application/font-woff"
      },
      {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=application/octet-stream"
      },
      {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        loader: "file-loader"
      },
      {
        test: /\.otf$/,
        loader: 'url-loader?limit=10000&mimetype=application/font-otf'
      },
      {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        loader: "url-loader?limit=10000&mimetype=image/svg+xml"
      }
    ]
  },
  resolve: {
    extensions: [".jsx", ".js"],
    alias: {
      // This is a quick fix:
      // Without pointing to the minified leaflet file
      // webpack includes 'leaflet-src.js'
      leaflet$: path.resolve(__dirname, "node_modules/leaflet/dist/leaflet.js")
    }
  }
};

let htmlPluginOptions = {
  template : "./src/index.html",
  title    : "Karte von morgen",
  favicon  : "./src/img/favicon.ico",
  inject   : 'body',
  pack_for_nightly : (process.env.NODE_ENV === APP_STAGES.NIGHTLY)
};

switch (process.env.NODE_ENV) {
  case APP_STAGES.LOCAL:
    plugins.push(new webpack.DefinePlugin({
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.LOCAL)
    }));
   plugins.push(new webpack.HotModuleReplacementPlugin());
   break;

  case APP_STAGES.NIGHTLY:
    htmlPluginOptions.minify = {
      removeComments        : true,
      collapseWhitespace    : true,
      conservativeCollapse  : false,
      minifyJS              : true,
      minifyCSS             : true,
    };

    // Enable React optimizations.
    plugins.push(new webpack.DefinePlugin({
      'process.env.STAGE'     : JSON.stringify('nightly'),
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.NIGHTLY)
    }));
    break;

  default:
    // production
    htmlPluginOptions.minify = {
      removeComments        : true,
      collapseWhitespace    : true,
      conservativeCollapse  : false,
      minifyJS              : true,
      minifyCSS             : true,
    };

    // Enable React optimizations.
    plugins.push(new webpack.DefinePlugin({
      'process.env.STAGE'     : JSON.stringify('production'),
      __DEVTOOLS__  : false,
      __STAGE__     : JSON.stringify(APP_STAGES.PRODUCTION)
    }));
}

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "index.html",
  chunks: ["app"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "businesscard.html",
  chunks: ["businesscard_widget"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "map.html",
  chunks: ["map_widget"]
}));

plugins.push(new HTMLPlugin({
  ...htmlPluginOptions,
  filename: "mapAndEntryList.html",
  chunks: ["mapAndEntryList_widget"]
}));

config.plugins = plugins;
module.exports = config;
<|endoftext|>


<commit_before>import path from 'path'
import webpack from 'webpack'
import autoprefixer from 'autoprefixer'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import dotenv from 'dotenv'

dotenv.config()

const START = process.env.npm_lifecycle_event === 'start'
const BUILD = process.env.npm_lifecycle_event === 'build'

const elmDir = path.resolve(__dirname, 'elm') + '/'
const jsDir = path.resolve(__dirname, 'js') + '/'

const config = {
  entry: './js/main.js',

  output: {
    path: './dist',
    filename: '/[hash].js',
    hotUpdateChunkFilename: '/[id].[hash].hot-update.js',
    hotUpdateMainFilename: '/[hash].hot-update.json'
  },

  resolve: {
    extensions: ['', '.js', '.elm']
  },

  module: {
    noParse: /\.elm$/,
    preLoaders: [
      { test: /\.js$/, include: [jsDir], loader: 'eslint-loader' }
    ],
    loaders: [
      { test: /\.js$/, include: [jsDir], loader: 'babel-loader' },
      { test: /\.(png|jpg|gif|svg|ttf|otf|eot|svg|woff2?)$/, loader: 'url-loader?limit=8192' },
      { test: /\.elm$/, include: [elmDir], loader: (START ? 'elm-hot!' : '') + 'elm-webpack?verbose=true&warn=true&debug=true&pathToMake=node_modules/.bin/elm-make' }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'html/index.html',
      inject: 'body',
      minify: require('./html-minifier.json')
    }),
    new webpack.DefinePlugin({
      '__CONFIG__': {
        basePath: JSON.stringify(process.env.BASE_PATH)
      }
    })
  ],

  postcss: [ autoprefixer({ browsers: ['last 2 versions']} ) ],

  eslint: {
    failOnWarning: true,
    failOnError: true
  },

  devServer: {
    stats: 'errors-only',
    historyApiFallback: true
  }
}

if (START) {
  config.module.loaders.push({ test: /\.less$/, loader: 'style!css!postcss-loader!less' })
}
if (BUILD) {
  // put styles in a separate file
  config.module.loaders.push({ test: /\.less$/, loader: ExtractTextPlugin.extract('style-loader', 'css!postcss-loader!less') })
  config.plugins.push(new ExtractTextPlugin('/[hash].css'))

  // disable UglifyJs warnings
  config.plugins.push(new webpack.optimize.UglifyJsPlugin({compress: {warnings: false }}))
}

export default config
<commit_msg>Update js and css paths with the basePath<commit_after>import path from 'path'
import webpack from 'webpack'
import autoprefixer from 'autoprefixer'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import dotenv from 'dotenv'

dotenv.config()

const START = process.env.npm_lifecycle_event === 'start'
const BUILD = process.env.npm_lifecycle_event === 'build'

const elmDir = path.resolve(__dirname, 'elm') + '/'
const jsDir = path.resolve(__dirname, 'js') + '/'

const config = {
  entry: './js/main.js',

  output: {
    path: './dist',
    filename: process.env.BASE_PATH + '/[hash].js',
    hotUpdateChunkFilename: process.env.BASE_PATH + '/[id].[hash].hot-update.js',
    hotUpdateMainFilename: process.env.BASE_PATH + '/[hash].hot-update.json'
  },

  resolve: {
    extensions: ['', '.js', '.elm']
  },

  module: {
    noParse: /\.elm$/,
    preLoaders: [
      { test: /\.js$/, include: [jsDir], loader: 'eslint-loader' }
    ],
    loaders: [
      { test: /\.js$/, include: [jsDir], loader: 'babel-loader' },
      { test: /\.(png|jpg|gif|svg|ttf|otf|eot|svg|woff2?)$/, loader: 'url-loader?limit=8192' },
      { test: /\.elm$/, include: [elmDir], loader: (START ? 'elm-hot!' : '') + 'elm-webpack?verbose=true&warn=true&debug=true&pathToMake=node_modules/.bin/elm-make' }
    ]
  },

  plugins: [
    new HtmlWebpackPlugin({
      template: 'html/index.html',
      inject: 'body',
      minify: require('./html-minifier.json')
    }),
    new webpack.DefinePlugin({
      '__CONFIG__': {
        basePath: JSON.stringify(process.env.BASE_PATH)
      }
    })
  ],

  postcss: [ autoprefixer({ browsers: ['last 2 versions']} ) ],

  eslint: {
    failOnWarning: true,
    failOnError: true
  },

  devServer: {
    stats: 'errors-only',
    historyApiFallback: true
  }
}

if (START) {
  config.module.loaders.push({ test: /\.less$/, loader: 'style!css!postcss-loader!less' })
}
if (BUILD) {
  // put styles in a separate file
  config.module.loaders.push({ test: /\.less$/, loader: ExtractTextPlugin.extract('style-loader', 'css!postcss-loader!less') })
  config.plugins.push(new ExtractTextPlugin(process.env.BASE_PATH + '/[hash].css'))

  // disable UglifyJs warnings
  config.plugins.push(new webpack.optimize.UglifyJsPlugin({compress: {warnings: false }}))
}

export default config
<|endoftext|>


<commit_before>import process from 'process';
import webpack from 'webpack';

const aui_css = __dirname + '/node_modules/@atlassian/aui/dist/aui/css/';
const minimize
    = process.argv.indexOf('-p') != -1
        || process.argv.indexOf('--optimize-minimize') != -1;
const strophe = /\/node_modules\/strophe(js-plugins)?\/.*\.js$/;

// The base Webpack configuration to bundle the JavaScript artifacts of
// jitsi-meet such as app.bundle.js and external_api.js.
const config = {
    devtool: 'source-map',
    module: {
        loaders: [{
            // Transpile ES2015 (aka ES6) to ES5.

            exclude: [
                __dirname + '/modules/RTC/adapter.screenshare.js',
                __dirname + '/node_modules/'
            ],
            loader: 'babel',
            test: /\.js$/
        },{
            // Expose jquery as the globals $ and jQuery because it is expected
            // to be available in such a form by multiple jitsi-meet
            // dependencies including AUI, lib-jitsi-meet.

            loader: 'expose?$!expose?jQuery',
            test: /\/node_modules\/jquery\/.*\.js$/
        },{
            // Disable AMD for the Strophe.js library or its imports will fail
            // at runtime.

            loader: 'imports?define=>false&this=>window',
            test: strophe
        },{
            // Allow CSS to be imported into JavaScript.

            loaders: [
                'style',
                'css'
            ],
            test: /\.css$/
        },{
            // Emit the static assets of AUI such as images that are referenced
            // by CSS into the output path.

            include: aui_css,
            loader: 'file',
            query: {
                context: aui_css,
                name: '[path][name].[ext]'
            },
            test: /\.(gif|png|svg)$/
        }],
        noParse: [
            // Do not parse the files of the Strophe.js library or at least
            // parts of the properties of the Strophe global variable will be
            // missing and strophejs-plugins will fail at runtime.
            strophe
        ]
    },
    node: {
        // Allow the use of the real filename of the module being executed. By
        // default Webpack does not leak path-related information and provides a
        // value that is a mock (/index.js).
        __filename: true
    },
    output: {
        filename: '[name]' + (minimize ? '.min' : '') + '.js',
        libraryTarget: 'umd',
        path: __dirname + '/build',
        sourceMapFilename: '[name].' + (minimize ? 'min' : 'js') + '.map'
    },
    resolve: {
        alias: {
            aui:
                '@atlassian/aui/dist/aui/js/aui'
                    + (minimize ? '.min' : '')
                    + '.js',
            'aui-experimental':
                '@atlassian/aui/dist/aui/js/aui-experimental'
                    + (minimize ? '.min' : '')
                    + '.js',
            jquery: 'jquery/dist/jquery' + (minimize ? '.min' : '') + '.js',
            'jQuery-Impromptu':
                'jQuery-Impromptu/dist/jquery-impromptu'
                    + (minimize ? '.min' : '')
                    + '.js',
        },
        packageAlias: 'browser'
    }
};

export default [{
    // The Webpack configuration to bundle app.bundle.js (aka APP).

    ...config,
    entry: {
       'app.bundle': './app.js'
    },
    output: {
        ...config.output,
        library: 'APP'
    }
}, {
    // The Webpack configuration to bundle external_api.js (aka
    // JitsiMeetExternalAPI).

    ...config,
    entry: {
       'external_api': './modules/API/external/external_api.js'
    },
    output: {
        ...config.output,
        library: 'JitsiMeetExternalAPI'
    }
}];
<commit_msg>Remove an unnecessary exclude from Webpack<commit_after>import process from 'process';
import webpack from 'webpack';

const aui_css = __dirname + '/node_modules/@atlassian/aui/dist/aui/css/';
const minimize
    = process.argv.indexOf('-p') != -1
        || process.argv.indexOf('--optimize-minimize') != -1;
const strophe = /\/node_modules\/strophe(js-plugins)?\/.*\.js$/;

// The base Webpack configuration to bundle the JavaScript artifacts of
// jitsi-meet such as app.bundle.js and external_api.js.
const config = {
    devtool: 'source-map',
    module: {
        loaders: [{
            // Transpile ES2015 (aka ES6) to ES5.

            exclude: __dirname + '/node_modules/',
            loader: 'babel',
            test: /\.js$/
        },{
            // Expose jquery as the globals $ and jQuery because it is expected
            // to be available in such a form by multiple jitsi-meet
            // dependencies including AUI, lib-jitsi-meet.

            loader: 'expose?$!expose?jQuery',
            test: /\/node_modules\/jquery\/.*\.js$/
        },{
            // Disable AMD for the Strophe.js library or its imports will fail
            // at runtime.

            loader: 'imports?define=>false&this=>window',
            test: strophe
        },{
            // Allow CSS to be imported into JavaScript.

            loaders: [
                'style',
                'css'
            ],
            test: /\.css$/
        },{
            // Emit the static assets of AUI such as images that are referenced
            // by CSS into the output path.

            include: aui_css,
            loader: 'file',
            query: {
                context: aui_css,
                name: '[path][name].[ext]'
            },
            test: /\.(gif|png|svg)$/
        }],
        noParse: [
            // Do not parse the files of the Strophe.js library or at least
            // parts of the properties of the Strophe global variable will be
            // missing and strophejs-plugins will fail at runtime.
            strophe
        ]
    },
    node: {
        // Allow the use of the real filename of the module being executed. By
        // default Webpack does not leak path-related information and provides a
        // value that is a mock (/index.js).
        __filename: true
    },
    output: {
        filename: '[name]' + (minimize ? '.min' : '') + '.js',
        libraryTarget: 'umd',
        path: __dirname + '/build',
        sourceMapFilename: '[name].' + (minimize ? 'min' : 'js') + '.map'
    },
    resolve: {
        alias: {
            aui:
                '@atlassian/aui/dist/aui/js/aui'
                    + (minimize ? '.min' : '')
                    + '.js',
            'aui-experimental':
                '@atlassian/aui/dist/aui/js/aui-experimental'
                    + (minimize ? '.min' : '')
                    + '.js',
            jquery: 'jquery/dist/jquery' + (minimize ? '.min' : '') + '.js',
            'jQuery-Impromptu':
                'jQuery-Impromptu/dist/jquery-impromptu'
                    + (minimize ? '.min' : '')
                    + '.js',
        },
        packageAlias: 'browser'
    }
};

export default [{
    // The Webpack configuration to bundle app.bundle.js (aka APP).

    ...config,
    entry: {
       'app.bundle': './app.js'
    },
    output: {
        ...config.output,
        library: 'APP'
    }
}, {
    // The Webpack configuration to bundle external_api.js (aka
    // JitsiMeetExternalAPI).

    ...config,
    entry: {
       'external_api': './modules/API/external/external_api.js'
    },
    output: {
        ...config.output,
        library: 'JitsiMeetExternalAPI'
    }
}];
<|endoftext|>


<commit_before>var webpack = require('webpack');
var baseConfig = require('./webpack.base.config');
var SpritesmithPlugin = require('webpack-spritesmith');
var BundleTracker = require('webpack-bundle-tracker');
var path = require('path');
var nodeModulesDir = path.resolve(__dirname, 'node_modules');

baseConfig[1].entry = [
  'webpack-dev-server/client?http://localhost:3000',
  'webpack/hot/only-dev-server',
  'bootstrap-loader',
  './assets/js/index',
]

baseConfig[0].output['publicPath'] = 'http://localhost:3000/assets/bundles/';
baseConfig[1].output = {
  path: path.resolve('./assets/bundles/'),
  publicPath: 'http://localhost:3000/assets/bundles/',
  filename: '[name].js',
}

baseConfig[1].module.loaders.push({
  test: /\.jsx?$/,
  exclude: [nodeModulesDir],
  loaders: ['react-hot-loader', 'babel-loader?presets[]=react,presets[]=es2015']
});

baseConfig[1].plugins = [
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NoEmitOnErrorsPlugin(),  // don't reload if there is an error
  new SpritesmithPlugin({
      src: {
        cwd: path.resolve(__dirname, 'assets/images/'),
        glob: '*.png'
      },
      target: {
        image: path.resolve(__dirname, 'assets/images/spritesmith-generated/sprite.png'),
        css: path.resolve(__dirname, 'assets/sass/vendor/spritesmith.scss')
      },
      retina: '@2x'
  }),
  new BundleTracker({
    filename: './webpack-stats.json'
  }),
  new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery",
    Tether: "tether",
    "window.Tether": "tether",
    Alert: "exports-loader?Alert!bootstrap/js/dist/alert",
    Button: "exports-loader?Button!bootstrap/js/dist/button",
    Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
    Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
    Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
    Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
    Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
    Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
    Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
    Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
    Util: "exports-loader?Util!bootstrap/js/dist/util",
  })
]

module.exports = baseConfig;
<commit_msg>adds NamedModulesPlugin to local webpack config to show plugins names on hot reloads<commit_after>var webpack = require('webpack');
var baseConfig = require('./webpack.base.config');
var SpritesmithPlugin = require('webpack-spritesmith');
var BundleTracker = require('webpack-bundle-tracker');
var path = require('path');
var nodeModulesDir = path.resolve(__dirname, 'node_modules');

baseConfig[1].entry = [
  'webpack-dev-server/client?http://localhost:3000',
  'webpack/hot/only-dev-server',
  'bootstrap-loader',
  './assets/js/index',
]

baseConfig[0].output['publicPath'] = 'http://localhost:3000/assets/bundles/';
baseConfig[1].output = {
  path: path.resolve('./assets/bundles/'),
  publicPath: 'http://localhost:3000/assets/bundles/',
  filename: '[name].js',
}

baseConfig[1].module.loaders.push({
  test: /\.jsx?$/,
  exclude: [nodeModulesDir],
  loaders: ['react-hot-loader', 'babel-loader?presets[]=react,presets[]=es2015']
});

baseConfig[1].plugins = [
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(),
  new webpack.NoEmitOnErrorsPlugin(),  // don't reload if there is an error
  new SpritesmithPlugin({
      src: {
        cwd: path.resolve(__dirname, 'assets/images/'),
        glob: '*.png'
      },
      target: {
        image: path.resolve(__dirname, 'assets/images/spritesmith-generated/sprite.png'),
        css: path.resolve(__dirname, 'assets/sass/vendor/spritesmith.scss')
      },
      retina: '@2x'
  }),
  new BundleTracker({
    filename: './webpack-stats.json'
  }),
  new webpack.ProvidePlugin({
    $: "jquery",
    jQuery: "jquery",
    "window.jQuery": "jquery",
    Tether: "tether",
    "window.Tether": "tether",
    Alert: "exports-loader?Alert!bootstrap/js/dist/alert",
    Button: "exports-loader?Button!bootstrap/js/dist/button",
    Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
    Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
    Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
    Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
    Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
    Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
    Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
    Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
    Util: "exports-loader?Util!bootstrap/js/dist/util",
  })
]

module.exports = baseConfig;
<|endoftext|>


<commit_before>'use strict';

let fs = require('fs');
let path = require('path');
let fse = require('fs-extra');
let shell = require('shelljs');
let colors = require('colors');
let inquirer = require('inquirer');

const port = 8080;
const task = process.argv[2].substring(1);
const buildjs = process.argv[3] == 'js';
const sourcePath = path.join(__dirname, '../src');
const outputPath = path.join(__dirname, '../dist');

let start = () => {
    function reboot ( err ) {
        if (/listen EADDRINUSE/.test(err.toString())) {
            console.log(`\n${ port } is aleary in use. Ctrl+C to leave or input a PID to kill：`.green);
            Promise.resolve(`lsof -i tcp:${ port }`).then(step4).then(step5).then(( pid ) => {
                return `kill ${ pid }`;
            }).then(step4).catch(( err ) => {
                console.log(err.toString().red);
            }).then(start);
        } else {
            console.log(err.toString().red);
        }
    }
    if (task == 'dev') {
        step3().then(() => {
            return `webpack-dev-server --inline --quiet --devtool eval --progress --colors --content-base ./src/ --hot --config ./webpack/webpack.dev.js --host 0.0.0.0 --port ${ port }`;
        }).then(step4).catch(reboot);
    }
    if (task == 'build') {
        if (buildjs) {
            step3().then(step6).then(step7).then(( option ) => {
                return step1().then(() => {
                    return `webpack --progress --colors --config ./webpack/webpack.build.js${ option }`;
                });
            }).then(step4).then(( cmd ) => {
                return `${ cmd } --uglify`;
            }).then(step4).then(() => {
                console.log('build complete!'.green);
            }).catch((err) => {
                console.log(err.toString().red);
            });
        } else {
            step1().then(step2).then(step3).then(() => {
                return `webpack --progress --colors --config ./webpack/webpack.build.js`;
            }).then(step4).then(() => {
                console.log('build complete!'.green);
            }).catch(( err ) => {
                console.log(err.toString().red);
            });
        }
    }
};

/**
 * [step1] fse.remove -- Remove old files
 * @return {Promise} remove_success
 */
let step1 = () => new Promise(( resolve, reject ) => {
    fse.remove(path.join(outputPath), ( err ) => {
        if (err) {
            reject(err);
            return;
        }
        resolve();
    });
});

/**
 * [step2] fse.copySync -- Copy files like `html` or `images`
 * @return {Promise} copy_success
 */
let step2 = () => new Promise(( resolve, reject ) => {
    fs.readdir(sourcePath, ( err, files ) => {
        if (err) {
            reject(err);
            return;
        }
        files.forEach(( filename ) => {
            let file = path.join(sourcePath, filename);
            if (filename[0] === '.') {
                return;
            }
            if (fs.statSync(file).isDirectory()) {
                if (filename == 'entry') {
                    return;
                }
                if (filename == 'package') {
                    return;
                }
            }
            if (fs.statSync(file).isFile()) {
                if (path.extname(file) == '.ejs') {
                    return;
                }
                if (path.extname(file) == '.html') {
                    return;
                }
                if (path.extname(file) == '.appcache') {
                    return;
                }
            }
            fse.copySync(file, path.join(outputPath, filename));
        });
        resolve();
    });
});

/**
 * [step3] fse.outputJson -- Create `webpack.entry.json` dynamically
 * @return {Promise} create_entry_success
 */
let step3 = () => new Promise(( resolve, reject ) => {
    let entry = {};
    let entryPath = path.join(sourcePath, 'entry');
    fs.readdir(entryPath, ( err, files ) => {
        if (err) {
            reject(err);
            return;
        }
        files.forEach(( filename ) => {
            let file = path.join(entryPath, filename);
            if (fs.statSync(file).isFile() && path.extname(file) == '.js') {
                entry[path.basename(filename, '.js')] = file;
            }
        });
        fse.outputJson(path.join(__dirname, 'webpack.entry.json'), entry, ( err ) => {
            if (err) {
                reject(err);
                return;
            }
            resolve(entry);
        });
    });
});

/**
 * [step4] shell.exec -- Exec command
 * @return {Promise} exec_command_success
 */
let step4 = ( cmd ) => new Promise(( resolve, reject ) => {
    let result = shell.exec(cmd);
    if (result.code === 0) {
        resolve(cmd);
    } else {
        reject(result.stderr);
    }
});

/**
 * [step5] inquirer.prompt -- Get PID
 * @return {Promise} get_pid_success
 */
let step5 = () => new Promise(( resolve, reject ) => {
    inquirer.prompt([{
        type : 'input',
        name : 'pid',
        message : 'PID:',
    }]).then(( answers ) => {
        resolve(answers.pid);
    }).catch(( err ) => {
        reject(err);
    });
});

/**
 * [step6] inquirer.prompt -- Get js file
 * @return {Promise} get_js_success
 */
let step6 = ( entry ) => new Promise(( resolve, reject ) => {
    let choices = Object.keys(entry);
    if (choices.length) {
        choices.forEach(( file, index ) => {
            choices[index] = file + '.js';
        });
        inquirer.prompt([{
            type : 'list',
            name : 'file',
            message : 'Select a file to pack:',
            choices,
        }]).then(( answers ) => {
            let file = path.basename(answers.file, '.js');
            let js = {};
            js[file] = entry[file];
            fse.outputJson(path.join(__dirname, 'webpack.entry.json'), js, ( err ) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve(js[file]);
            });
        }).catch(( err ) => {
            reject(err);
        });
    } else {
        reject('There is any js file in entry.');
    }
});

/**
 * [step7] fs.readFile -- Get js webpack config
 * @return {Promise} get_config_success
 */
let step7 = ( filepath ) => new Promise(( resolve, reject ) => {
    fs.readFile(filepath, (err, buffer) => {
        if (err) {
            reject(err);
            return;
        }
        let result = '';
        let match = buffer.toString().match(/\/\*(.|\n)*?\*\//);
        if (match) {
            let comments = match[0].match(/@.*/g);
            if (comments && comments[0].trim().substring('1') == 'webpack') {
                if (comments[1] && /^@library\b/.test(comments[1]) && !/^@library$/.test(comments[1].trim())) {
                    result += comments[1].trim().replace(' ', '=').replace(/\s/g, '').replace('@', ' --');
                }
                if (comments[2] && /^@libraryTarget\b/.test(comments[2]) && !/^@library$/.test(comments[2].trim())) {
                    result += comments[2].trim().replace(' ', '=').replace(/\s/g, '').replace('@', ' --');
                }
            }
        }
        resolve(result + ' --build=js');
    });
});

start();
<commit_msg>update webpack<commit_after>'use strict';

let fs = require('fs');
let path = require('path');
let fse = require('fs-extra');
let shell = require('shelljs');
let colors = require('colors');
let inquirer = require('inquirer');

const port = 8080;
const task = process.argv[2].substring(1);
const buildjs = process.argv[3] == 'js';
const sourcePath = path.join(__dirname, '../src');
const outputPath = path.join(__dirname, '../dist');

let version = ['x', 'x', 'x'];
const regexp = /^((^|\.)(0|([1-9](\d+)?))){1,3}$/;
if (process.argv[3] && regexp.test(process.argv[3])) {
    process.argv[3].split('.').forEach(( value, index ) => {
        version[index] = value;
    });
}

let start = () => {
    function reboot ( err ) {
        if (/listen EADDRINUSE/.test(err.toString())) {
            console.log(`\n${ port } is aleary in use. Ctrl+C to leave or input a PID to kill：`.green);
            Promise.resolve(`lsof -i tcp:${ port }`).then(step2).then(step3).then(( pid ) => {
                return `kill ${ pid }`;
            }).then(step2).catch(( err ) => {
                console.log(err.toString().red);
            }).then(start);
        } else {
            console.log(err.toString().red);
        }
    }
    if (task == 'dev') {
        step1().then(() => {
            return `webpack-dev-server --inline --quiet --devtool eval --progress --colors --content-base ./src/ --hot --config ./webpack/webpack.dev.js --host 0.0.0.0 --port ${ port } --version=${ version.join('.') }`;
        }).then(step2).catch(reboot);
    }
    if (task == 'build') {
        if (buildjs) {
            step1().then(step4).then(step5).then(( option ) => {
                return `webpack --progress --colors --config ./webpack/webpack.build.js${ option }`;
            }).then(step2).then(( cmd ) => {
                return `${ cmd } --uglify`;
            }).then(step2).then(() => {
                console.log('build complete!'.green);
            }).catch((err) => {
                console.log(err.toString().red);
            });
        } else {
            step1().then(() => {
                return `webpack --progress --colors --config ./webpack/webpack.build.js --version=${ version.join('.') }`;
            }).then(step2).then(() => {
                console.log('build complete!'.green);
            }).catch(( err ) => {
                console.log(err.toString().red);
            });
        }
    }
};

/**
 * [step1] fse.outputJson -- Create `webpack.entry.json` dynamically
 * @return {Promise} create_entry_success
 */
let step1 = () => new Promise(( resolve, reject ) => {
    let entry = {};
    console.log('create entry with:', version.join('.').green);
    let versionRegexp = version.slice();
    versionRegexp.forEach(( value, index ) => {
        if (value === 'x') {
            versionRegexp[index] = '(0|[1-9](\\d+)?)';
        }
    });
    versionRegexp = new RegExp('^' + versionRegexp.join('\\.') + '$');
    Promise.all([
        new Promise(( resolve, reject ) => {
            let entryPath = path.join(sourcePath, 'entry');
            fs.readdir(entryPath, ( err, files ) => {
                if (err) {
                    reject(err);
                    return;
                }
                files.forEach(( filename ) => {
                    let file = path.join(entryPath, filename);
                    if (fs.statSync(file).isFile() && path.extname(file) == '.js') {
                        entry[`${ path.basename(filename, '.js') }`] = file;
                    }
                });
                resolve();
            });
        }),
        new Promise(( resolve, reject ) => {
            let packagePath = path.join(sourcePath, 'package');
            fs.readdirSync(packagePath).forEach(( packageVersion ) => {
                let packageVersionJs = path.join(packagePath, packageVersion, 'index.js');
                let packageVersionJson = path.join(packagePath, packageVersion, 'package.json');
                if (fs.existsSync(packageVersionJson) && fs.statSync(packageVersionJson).isFile()) {
                    if (versionRegexp.test(packageVersion)) {
                        entry[`package/${ packageVersion }`] = packageVersionJs;
                    }
                }
            });
            resolve();
        }),
    ]).then(() => {
        fse.outputJson(path.join(__dirname, 'webpack.entry.json'), entry, ( err ) => {
            if (err) {
                reject(err);
                return;
            }
            // console.log(entry);
            resolve(entry);
        });
    }).catch(( err ) => {
        reject(err);
    });
});

/**
 * [step2] shell.exec -- Exec command
 * @param  {String} cmd command
 * @return {Promise} exec_command_success
 */
let step2 = ( cmd ) => new Promise(( resolve, reject ) => {
    let result = shell.exec(cmd);
    if (result.code === 0) {
        resolve(cmd);
    } else {
        reject(result.stderr);
    }
});

/**
 * [step3] inquirer.prompt -- Get PID
 * @return {Promise} get_pid_success
 */
let step3 = () => new Promise(( resolve, reject ) => {
    inquirer.prompt([{
        type : 'input',
        name : 'pid',
        message : 'PID:',
    }]).then(( answers ) => {
        resolve(answers.pid);
    }).catch(( err ) => {
        reject(err);
    });
});

/**
 * [step4] inquirer.prompt -- Get js file
 * @param  {JSON} entry entry
 * @return {Promise} get_js_success
 */
let step4 = ( entry ) => new Promise(( resolve, reject ) => {
    let choices = Object.keys(entry);
    if (choices.length) {
        choices.forEach(( file, index ) => {
            choices[index] = file + '.js';
        });
        inquirer.prompt([{
            type : 'list',
            name : 'file',
            message : 'Select a file to pack:',
            choices,
        }]).then(( answers ) => {
            let file = path.basename(answers.file, '.js');
            let js = {};
            js[file] = entry[file];
            fse.outputJson(path.join(__dirname, 'webpack.entry.json'), js, ( err ) => {
                if (err) {
                    reject(err);
                    return;
                }
                resolve(js[file]);
            });
        }).catch(( err ) => {
            reject(err);
        });
    } else {
        reject('There is any js file in entry.');
    }
});

/**
 * [step5] fs.readFile -- Get js webpack config
 * @param  {String} filepath filepath
 * @return {Promise} get_config_success
 */
let step5 = ( filepath ) => new Promise(( resolve, reject ) => {
    fs.readFile(filepath, (err, buffer) => {
        if (err) {
            reject(err);
            return;
        }
        let result = '';
        let match = buffer.toString().match(/\/\*(.|\n)*?\*\//);
        if (match) {
            let comments = match[0].match(/@.*/g);
            if (comments && comments[0].trim().substring('1') == 'webpack') {
                if (comments[1] && /^@library\b/.test(comments[1]) && !/^@library$/.test(comments[1].trim())) {
                    result += comments[1].trim().replace(' ', '=').replace(/\s/g, '').replace('@', ' --');
                }
                if (comments[2] && /^@libraryTarget\b/.test(comments[2]) && !/^@library$/.test(comments[2].trim())) {
                    result += comments[2].trim().replace(' ', '=').replace(/\s/g, '').replace('@', ' --');
                }
            }
        }
        resolve(result + ' --build=js');
    });
});

start();
<|endoftext|>


<commit_before>var fs = require("fs");
var Benchmark = require("benchmark");
var memwatch = require('memwatch');
var Mask = require("./mask");

function readMask (path, callback) {
  var rs = fs.createReadStream(path);
  rs.on("readable", function () {
    var buffer = rs.read();
    var ab = new ArrayBuffer(buffer.length);
    var u8 = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; i++) {
      u8[i] = buffer[i];
    }
    var m = new Mask.PBM();
    return m.load(ab, callback);
  });
}

function readBoth (a, b, done) {
  readMask(a, function (a_) {
    readMask(b, function (b_) {
      return done(a_, b_);
    });
  });
}

var hd = new memwatch.HeapDiff();
readMask("test-data/frame-10-10-ascii.pbm",
         function (_a) {
           var diff = hd.end();
           console.log("Reading \"frame-10-10-ascii.pbm\" costs",
                       diff.change.size + ".");
         });

readBoth("test-data/frame-10-10-ascii.pbm",
         "test-data/dot-10-10-ascii.pbm",
         function (a_, b_) {
           new Benchmark.Suite().add("Mask.PBM#collidesAt", function () {
             Mask.collision(a_, b_);
           }).on("cycle", function (event) {
             console.log(String(event.target));
           }).run();
         });

<commit_msg>more benchmarks<commit_after>var fs = require("fs");
var Benchmark = require("benchmark");
var memwatch = require('memwatch');
var Mask = require("./mask");

function readMask (path, callback) {
  var rs = fs.createReadStream(path);
  rs.on("readable", function () {
    var buffer = rs.read();
    var ab = new ArrayBuffer(buffer.length);
    var u8 = new Uint8Array(ab);
    for (var i = 0; i < buffer.length; i++) {
      u8[i] = buffer[i];
    }
    var m = new Mask.PBM();
    return m.load(ab, callback);
  });
}

function readBoth (a, b, done) {
  readMask(a, function (a_) {
    readMask(b, function (b_) {
      return done(a_, b_);
    });
  });
}

var hd = new memwatch.HeapDiff();
readMask("test-data/frame-10-10-ascii.pbm",
         function (_a) {
           var diff = hd.end();
           console.log("Reading \"frame-10-10-ascii.pbm\" costs",
                       diff.change.size + ".");
         });

var frame = "test-data/frame-10-10-ascii.pbm";
var dot = "test-data/dot-10-10-ascii.pbm";
readBoth(frame, dot, function (frame_, dot_) {5
  new Benchmark.Suite().
    add("Mask.collision [frame@0/0, dot@0/0 ]", function () {
      Mask.collision(frame_, dot_);
    }).
    add("Mask.collision [frame@9/9, dot@0/0 ]", function () {
      Mask.collision(frame_.at(9, 9), dot_);
    }).
    add("Mask.collision [dot@0/0, frame@9/9 ]", function () {
      Mask.collision(dot_, frame_.at(9, 9));
    }).
    add("Mask.collision [frame@0/0, bounding]", function () {
      Mask.collision(frame_, Mask.Box.bounding(frame_));
    }).
    add("Mask.collision [dot@0/0, bounding  ]", function () {
      Mask.collision(dot_, Mask.Box.bounding(dot_));
    }).
    add("Mask.collision [10/10@0/0, 2/2@0/0 ]", function () {
      Mask.collision(new Mask.Box(10, 10),
                     new Mask.Box(2, 2));
    }).
    add("Mask.collision [2/2@0/0, 10/10@0/0 ]", function () {
      Mask.collision(new Mask.Box(2, 2),
                     new Mask.Box(10, 10));
    }).
    add("Mask.collision [2/2@2/2, 4/4@0/0   ]", function () {
      Mask.collision(new Mask.Box(2, 2).at(2, 2),
                     new Mask.Box(4, 4));
    }).
    on("cycle", function (event) {
     console.log(event.target.toString());
    }).
    run();
});
<|endoftext|>


<commit_before>function generate (inputs) {

    var previous_autotune = inputs.previous_autotune;
    var pumpprofile = inputs.pumpprofile;
    var pumpbasalprofile = pumpprofile.basalprofile;
    //console.error(pumpbasalprofile);
    var basalprofile = previous_autotune.basalprofile;
    //console.error(basalprofile);
    var isf_profile = previous_autotune.isfProfile;
    //console.error(isf_profile);
    var isf = isf_profile.sensitivities[0].sensitivity;
    //console.error(isf);
    var carb_ratio = previous_autotune.carb_ratio;
    //console.error(carb_ratio);
    var csf = isf / carb_ratio;
    if (pumpprofile) { pump_isf_profile = pumpprofile.isfProfile; }
    if (pump_isf_profile && pump_isf_profile.sensitivities[0]) {
        pumpISF = pump_isf_profile.sensitivities[0].sensitivity;
    }
    var pump_carb_ratio = pumpprofile.carb_ratio;
    var pumpCSF = pumpISF / pump_carb_ratio;
    //console.error(csf);
    var prepped_glucose = inputs.prepped_glucose;
    var csf_glucose = prepped_glucose.csf_glucose_data;
    //console.error(csf_glucose[0]);
    var isf_glucose = prepped_glucose.isf_glucose_data;
    //console.error(isf_glucose[0]);
    var basal_glucose = prepped_glucose.basal_glucose_data;
    //console.error(basal_glucose[0]);

    // convert the basal profile to hourly if it isn't already
    hourlybasalprofile = [];
    hourlypumpprofile = [];
    for (var i=0; i < 24; i++) {
        // aututuned basal profile
        for (var j=0; j < basalprofile.length; ++j) {
            if (basalprofile[j].minutes <= i * 60) {
                hourlybasalprofile[i] = JSON.parse(JSON.stringify(basalprofile[j]));
            }
        }
        hourlybasalprofile[i].i=i;
        hourlybasalprofile[i].minutes=i*60;
        hourlybasalprofile[i].rate=Math.round(hourlybasalprofile[i].rate*1000)/1000
        // pump basal profile
        if (pumpbasalprofile[0]) {
            for (var j=0; j < pumpbasalprofile.length; ++j) {
                //console.error(pumpbasalprofile[j]);
                if (pumpbasalprofile[j].minutes <= i * 60) {
                    hourlypumpprofile[i] = JSON.parse(JSON.stringify(pumpbasalprofile[j]));
                }
            }
            hourlypumpprofile[i].i=i;
            hourlypumpprofile[i].minutes=i*60;
            hourlypumpprofile[i].rate=Math.round(hourlypumpprofile[i].rate*1000)/1000
        }
    }
    //console.error(hourlypumpprofile);
    //console.error(hourlybasalprofile);

    // look at net deviations for each hour
    for (var hour=0; hour < 24; hour++) {
        var deviations = 0;
        for (var i=0; i < basal_glucose.length; ++i) {
            //console.error(basal_glucose[i].dateString);
            splitString = basal_glucose[i].dateString.split("T");
            timeString = splitString[1];
            splitTime = timeString.split(":");
            myHour = parseInt(splitTime[0]);
            if (hour == myHour) {
                //console.error(basal_glucose[i].deviation);
                deviations += parseFloat(basal_glucose[i].deviation);
            }
        }
        deviations = Math.round( deviations * 1000 ) / 1000
        //console.error("Hour",hour.toString(),"total deviations:",deviations,"mg/dL");
        // calculate how much less or additional basal insulin would have been required to eliminate the deviations
        // only apply 20% of the needed adjustment to keep things relatively stable
        basalNeeded = 0.2 * deviations / isf;
        basalNeeded = Math.round( basalNeeded * 1000 ) / 1000
        // if basalNeeded is positive, adjust each of the 1-3 hour prior basals by 10% of the needed adjustment
        console.error("Hour",hour,"basal adjustment needed:",basalNeeded,"U/hr");
        if (basalNeeded > 0 ) {
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                //console.error(offsetHour);
                hourlybasalprofile[offsetHour].rate += basalNeeded / 3;
                hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000
            }
        // otherwise, figure out the percentage reduction required to the 1-3 hour prior basals
        // and adjust all of them downward proportionally
        } else if (basalNeeded < 0) {
            var threeHourBasal = 0;
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                threeHourBasal += hourlybasalprofile[offsetHour].rate;
            }
            var adjustmentRatio = 1.0 + basalNeeded / threeHourBasal;
            console.error(adjustmentRatio);
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                hourlybasalprofile[offsetHour].rate = hourlybasalprofile[offsetHour].rate * adjustmentRatio;
                hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000
            }
        }
    }
    if (pumpbasalprofile[0]) {
        for (var hour=0; hour < 24; hour++) {
            //console.error(hourlybasalprofile[hour],hourlypumpprofile[hour].rate*1.2);
            var maxrate = hourlypumpprofile[hour].rate * 1.2;
            var minrate = hourlypumpprofile[hour].rate / 1.2;
            if (hourlybasalprofile[hour].rate > maxrate ) {
                console.error("Limiting hour",hour,"basal to",maxrate.toFixed(2),"(20% above pump basal of",hourlypumpprofile[hour].rate,")");
                hourlybasalprofile[hour].rate = hourlypumpprofile[hour].rate * 1.2;
            } else if (hourlybasalprofile[hour].rate < minrate ) {
                console.error("Limiting hour",hour,"basal to",minrate.toFixed(2),"(20% below pump basal of",hourlypumpprofile[hour].rate,")");
                hourlybasalprofile[hour].rate = hourlypumpprofile[hour].rate / 1.2;
            }
            hourlybasalprofile[hour].rate = Math.round(hourlybasalprofile[hour].rate*1000)/1000;
        }
    }

    console.error(hourlybasalprofile);
    basalprofile = hourlybasalprofile;

    // calculate median deviation and bgi in data attributable to ISF
    var deviations = [];
    var bgis = [];
    var avgDeltas = [];
    var ratios = [];
    var count = 0;
    for (var i=0; i < isf_glucose.length; ++i) {
       deviation = parseFloat(isf_glucose[i].deviation);
       deviations.push(deviation);
       bgi = parseFloat(isf_glucose[i].bgi);
       bgis.push(bgi);
       avgDelta = parseFloat(isf_glucose[i].avgDelta);
       avgDeltas.push(avgDelta);
       ratio = 1 + deviation / bgi;
       //console.error("Deviation:",deviation,"BGI:",bgi,"avgDelta:",avgDelta,"ratio:",ratio);
       ratios.push(ratio);
       count++;
    }
    avgDeltas.sort(function(a, b){return a-b});
    bgis.sort(function(a, b){return a-b});
    deviations.sort(function(a, b){return a-b});
    ratios.sort(function(a, b){return a-b});
    p50deviation = percentile(deviations, 0.50);
    p50bgi = percentile(bgis, 0.50);
    p50ratios = Math.round( percentile(ratios, 0.50) * 1000)/1000;

    // calculate what adjustments to ISF would have been necessary to bring median deviation to zero
    fullNewISF = isf * p50ratios;
    fullNewISF = Math.round( fullNewISF * 1000 ) / 1000;
    // and apply 10% of that adjustment
    var newISF = ( 0.9 * isf ) + ( 0.1 * fullNewISF );
    if (pumpISF) {
        var maxISF = pumpISF * 1.2;
        var minISF = pumpISF / 1.2;
        if (newISF > maxISF) {
            console.error("Limiting ISF to",maxISF.toFixed(2),"(20% above pump ISF of",pumpISF,")");
            newISF = maxISF;
        } else if (newISF < minISF) {
            console.error("Limiting ISF to",minISF.toFixed(2),"(20% below pump ISF of",pumpISF,")");
            newISF = minISF;
        }
    }
    newISF = Math.round( newISF * 1000 ) / 1000;
    //console.error(avgRatio);
    //console.error(newISF);
    console.error("p50deviation:",p50deviation,"p50bgi",p50bgi,"p50ratios:",p50ratios,"Old ISF:",isf,"fullNewISF:",fullNewISF,"newISF:",newISF);

    isf = newISF;

    // calculate net deviations while carbs are absorbing
    // measured from carb entry until COB and deviations both drop to zero

    var deviations = 0;
    var mealCarbs = 0;
    var totalMealCarbs = 0;
    var totalDeviations = 0;
    //console.error(csf_glucose[0].mealAbsorption);
    //console.error(csf_glucose[0]);
    for (var i=0; i < csf_glucose.length; ++i) {
        //console.error(csf_glucose[i].mealAbsorption, i);
        if ( csf_glucose[i].mealAbsorption === "start" ) {
            deviations = 0;
            mealCarbs = parseInt(csf_glucose[i].mealCarbs);
        } else if (csf_glucose[i].mealAbsorption === "end") {
            deviations += parseFloat(csf_glucose[i].deviation);
            // compare the sum of deviations from start to end vs. current CSF * mealCarbs
            //console.error(csf,mealCarbs);
            csfRise = csf * mealCarbs;
            //console.error(deviations,isf);
            console.error("csfRise:",csfRise,"deviations:",deviations);
            totalMealCarbs += mealCarbs;
            totalDeviations += deviations;

        } else {
            deviations += Math.max(0*previous_autotune.min_5m_carbimpact,parseFloat(csf_glucose[i].deviation));
            mealCarbs = Math.max(mealCarbs, parseInt(csf_glucose[i].mealCarbs));
        }
    }
    if (totalMealCarbs == 0) { totalMealCarbs += mealCarbs; }
    if (totalDeviations == 0) { totalDeviations += deviations; }
    //console.error(totalDeviations, totalMealCarbs);
    if (totalMealCarbs == 0) {
        fullNewCSF = csf;
    } else {
        fullNewCSF = Math.round( (totalDeviations / totalMealCarbs)*100 )/100;
    }
    newCSF = ( 0.9 * csf ) + ( 0.1 * fullNewCSF );
    if (pumpCSF) {
        var maxCSF = pumpCSF * 1.2;
        var minCSF = pumpCSF / 1.2;
        if (newCSF > maxCSF) {
            console.error("Limiting CSF to",maxCSF.toFixed(2),"(20% above pump CSF of",pumpCSF,")");
            newCSF = maxCSF;
        } else if (newCSF < minCSF) {
            console.error("Limiting CSF to",minCSF.toFixed(2),"(20% below pump CSF of",pumpCSF,")");
            newCSF = minCSF;
        } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); }
    }
    newCSF = Math.round( newCSF * 1000 ) / 1000;
    console.error("totalMealCarbs:",totalMealCarbs,"totalDeviations:",totalDeviations,"fullNewCSF:",fullNewCSF,"newCSF:",newCSF);
    csf = newCSF;

    // reconstruct updated version of previous_autotune as autotune_output
    autotune_output = previous_autotune;
    autotune_output.basalprofile = basalprofile;
    isf_profile.sensitivities[0].sensitivity = isf;
    autotune_output.isfProfile = isf_profile;
    autotune_output.csf = csf;
    carb_ratio = isf / csf;
    carb_ratio = Math.round( carb_ratio * 1000 ) / 1000;
    autotune_output.carb_ratio = carb_ratio;

    return autotune_output;
}

exports = module.exports = generate;

// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
function percentile(arr, p) {
    if (arr.length === 0) return 0;
    if (typeof p !== 'number') throw new TypeError('p must be a number');
    if (p <= 0) return arr[0];
    if (p >= 1) return arr[arr.length - 1];

    var index = arr.length * p,
        lower = Math.floor(index),
        upper = lower + 1,
        weight = index % 1;

    if (upper >= arr.length) return arr[lower];
    return arr[lower] * (1 - weight) + arr[upper] * weight;
}

// Returns the percentile of the given value in a sorted numeric array.
function percentRank(arr, v) {
    if (typeof v !== 'number') throw new TypeError('v must be a number');
    for (var i = 0, l = arr.length; i < l; i++) {
        if (v <= arr[i]) {
            while (i < l && v === arr[i]) i++;
            if (i === 0) return 0;
            if (v !== arr[i-1]) {
                i += (v - arr[i-1]) / (arr[i] - arr[i-1]);
            }
            return i / l;
        }
    }
    return 1;
}
<commit_msg>only set pumpCSF if setting pumpISF<commit_after>function generate (inputs) {

    var previous_autotune = inputs.previous_autotune;
    var pumpprofile = inputs.pumpprofile;
    var pumpbasalprofile = pumpprofile.basalprofile;
    //console.error(pumpbasalprofile);
    var basalprofile = previous_autotune.basalprofile;
    //console.error(basalprofile);
    var isf_profile = previous_autotune.isfProfile;
    //console.error(isf_profile);
    var isf = isf_profile.sensitivities[0].sensitivity;
    //console.error(isf);
    var carb_ratio = previous_autotune.carb_ratio;
    //console.error(carb_ratio);
    var csf = isf / carb_ratio;
    if (pumpprofile) { pump_isf_profile = pumpprofile.isfProfile; }
    if (pump_isf_profile && pump_isf_profile.sensitivities[0]) {
        pumpISF = pump_isf_profile.sensitivities[0].sensitivity;
        pump_carb_ratio = pumpprofile.carb_ratio;
        pumpCSF = pumpISF / pump_carb_ratio;
    }
    //console.error(csf);
    var prepped_glucose = inputs.prepped_glucose;
    var csf_glucose = prepped_glucose.csf_glucose_data;
    //console.error(csf_glucose[0]);
    var isf_glucose = prepped_glucose.isf_glucose_data;
    //console.error(isf_glucose[0]);
    var basal_glucose = prepped_glucose.basal_glucose_data;
    //console.error(basal_glucose[0]);

    // convert the basal profile to hourly if it isn't already
    hourlybasalprofile = [];
    hourlypumpprofile = [];
    for (var i=0; i < 24; i++) {
        // aututuned basal profile
        for (var j=0; j < basalprofile.length; ++j) {
            if (basalprofile[j].minutes <= i * 60) {
                hourlybasalprofile[i] = JSON.parse(JSON.stringify(basalprofile[j]));
            }
        }
        hourlybasalprofile[i].i=i;
        hourlybasalprofile[i].minutes=i*60;
        hourlybasalprofile[i].rate=Math.round(hourlybasalprofile[i].rate*1000)/1000
        // pump basal profile
        if (pumpbasalprofile[0]) {
            for (var j=0; j < pumpbasalprofile.length; ++j) {
                //console.error(pumpbasalprofile[j]);
                if (pumpbasalprofile[j].minutes <= i * 60) {
                    hourlypumpprofile[i] = JSON.parse(JSON.stringify(pumpbasalprofile[j]));
                }
            }
            hourlypumpprofile[i].i=i;
            hourlypumpprofile[i].minutes=i*60;
            hourlypumpprofile[i].rate=Math.round(hourlypumpprofile[i].rate*1000)/1000
        }
    }
    //console.error(hourlypumpprofile);
    //console.error(hourlybasalprofile);

    // look at net deviations for each hour
    for (var hour=0; hour < 24; hour++) {
        var deviations = 0;
        for (var i=0; i < basal_glucose.length; ++i) {
            //console.error(basal_glucose[i].dateString);
            splitString = basal_glucose[i].dateString.split("T");
            timeString = splitString[1];
            splitTime = timeString.split(":");
            myHour = parseInt(splitTime[0]);
            if (hour == myHour) {
                //console.error(basal_glucose[i].deviation);
                deviations += parseFloat(basal_glucose[i].deviation);
            }
        }
        deviations = Math.round( deviations * 1000 ) / 1000
        //console.error("Hour",hour.toString(),"total deviations:",deviations,"mg/dL");
        // calculate how much less or additional basal insulin would have been required to eliminate the deviations
        // only apply 20% of the needed adjustment to keep things relatively stable
        basalNeeded = 0.2 * deviations / isf;
        basalNeeded = Math.round( basalNeeded * 1000 ) / 1000
        // if basalNeeded is positive, adjust each of the 1-3 hour prior basals by 10% of the needed adjustment
        console.error("Hour",hour,"basal adjustment needed:",basalNeeded,"U/hr");
        if (basalNeeded > 0 ) {
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                //console.error(offsetHour);
                hourlybasalprofile[offsetHour].rate += basalNeeded / 3;
                hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000
            }
        // otherwise, figure out the percentage reduction required to the 1-3 hour prior basals
        // and adjust all of them downward proportionally
        } else if (basalNeeded < 0) {
            var threeHourBasal = 0;
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                threeHourBasal += hourlybasalprofile[offsetHour].rate;
            }
            var adjustmentRatio = 1.0 + basalNeeded / threeHourBasal;
            console.error(adjustmentRatio);
            for (var offset=-3; offset < 0; offset++) {
                offsetHour = hour + offset;
                if (offsetHour < 0) { offsetHour += 24; }
                hourlybasalprofile[offsetHour].rate = hourlybasalprofile[offsetHour].rate * adjustmentRatio;
                hourlybasalprofile[offsetHour].rate=Math.round(hourlybasalprofile[offsetHour].rate*1000)/1000
            }
        }
    }
    if (pumpbasalprofile[0]) {
        for (var hour=0; hour < 24; hour++) {
            //console.error(hourlybasalprofile[hour],hourlypumpprofile[hour].rate*1.2);
            var maxrate = hourlypumpprofile[hour].rate * 1.2;
            var minrate = hourlypumpprofile[hour].rate / 1.2;
            if (hourlybasalprofile[hour].rate > maxrate ) {
                console.error("Limiting hour",hour,"basal to",maxrate.toFixed(2),"(20% above pump basal of",hourlypumpprofile[hour].rate,")");
                hourlybasalprofile[hour].rate = hourlypumpprofile[hour].rate * 1.2;
            } else if (hourlybasalprofile[hour].rate < minrate ) {
                console.error("Limiting hour",hour,"basal to",minrate.toFixed(2),"(20% below pump basal of",hourlypumpprofile[hour].rate,")");
                hourlybasalprofile[hour].rate = hourlypumpprofile[hour].rate / 1.2;
            }
            hourlybasalprofile[hour].rate = Math.round(hourlybasalprofile[hour].rate*1000)/1000;
        }
    }

    console.error(hourlybasalprofile);
    basalprofile = hourlybasalprofile;

    // calculate median deviation and bgi in data attributable to ISF
    var deviations = [];
    var bgis = [];
    var avgDeltas = [];
    var ratios = [];
    var count = 0;
    for (var i=0; i < isf_glucose.length; ++i) {
       deviation = parseFloat(isf_glucose[i].deviation);
       deviations.push(deviation);
       bgi = parseFloat(isf_glucose[i].bgi);
       bgis.push(bgi);
       avgDelta = parseFloat(isf_glucose[i].avgDelta);
       avgDeltas.push(avgDelta);
       ratio = 1 + deviation / bgi;
       //console.error("Deviation:",deviation,"BGI:",bgi,"avgDelta:",avgDelta,"ratio:",ratio);
       ratios.push(ratio);
       count++;
    }
    avgDeltas.sort(function(a, b){return a-b});
    bgis.sort(function(a, b){return a-b});
    deviations.sort(function(a, b){return a-b});
    ratios.sort(function(a, b){return a-b});
    p50deviation = percentile(deviations, 0.50);
    p50bgi = percentile(bgis, 0.50);
    p50ratios = Math.round( percentile(ratios, 0.50) * 1000)/1000;

    // calculate what adjustments to ISF would have been necessary to bring median deviation to zero
    fullNewISF = isf * p50ratios;
    fullNewISF = Math.round( fullNewISF * 1000 ) / 1000;
    // and apply 10% of that adjustment
    var newISF = ( 0.9 * isf ) + ( 0.1 * fullNewISF );
    if (pumpISF) {
        var maxISF = pumpISF * 1.2;
        var minISF = pumpISF / 1.2;
        if (newISF > maxISF) {
            console.error("Limiting ISF to",maxISF.toFixed(2),"(20% above pump ISF of",pumpISF,")");
            newISF = maxISF;
        } else if (newISF < minISF) {
            console.error("Limiting ISF to",minISF.toFixed(2),"(20% below pump ISF of",pumpISF,")");
            newISF = minISF;
        }
    }
    newISF = Math.round( newISF * 1000 ) / 1000;
    //console.error(avgRatio);
    //console.error(newISF);
    console.error("p50deviation:",p50deviation,"p50bgi",p50bgi,"p50ratios:",p50ratios,"Old ISF:",isf,"fullNewISF:",fullNewISF,"newISF:",newISF);

    isf = newISF;

    // calculate net deviations while carbs are absorbing
    // measured from carb entry until COB and deviations both drop to zero

    var deviations = 0;
    var mealCarbs = 0;
    var totalMealCarbs = 0;
    var totalDeviations = 0;
    //console.error(csf_glucose[0].mealAbsorption);
    //console.error(csf_glucose[0]);
    for (var i=0; i < csf_glucose.length; ++i) {
        //console.error(csf_glucose[i].mealAbsorption, i);
        if ( csf_glucose[i].mealAbsorption === "start" ) {
            deviations = 0;
            mealCarbs = parseInt(csf_glucose[i].mealCarbs);
        } else if (csf_glucose[i].mealAbsorption === "end") {
            deviations += parseFloat(csf_glucose[i].deviation);
            // compare the sum of deviations from start to end vs. current CSF * mealCarbs
            //console.error(csf,mealCarbs);
            csfRise = csf * mealCarbs;
            //console.error(deviations,isf);
            console.error("csfRise:",csfRise,"deviations:",deviations);
            totalMealCarbs += mealCarbs;
            totalDeviations += deviations;

        } else {
            deviations += Math.max(0*previous_autotune.min_5m_carbimpact,parseFloat(csf_glucose[i].deviation));
            mealCarbs = Math.max(mealCarbs, parseInt(csf_glucose[i].mealCarbs));
        }
    }
    if (totalMealCarbs == 0) { totalMealCarbs += mealCarbs; }
    if (totalDeviations == 0) { totalDeviations += deviations; }
    //console.error(totalDeviations, totalMealCarbs);
    if (totalMealCarbs == 0) {
        fullNewCSF = csf;
    } else {
        fullNewCSF = Math.round( (totalDeviations / totalMealCarbs)*100 )/100;
    }
    newCSF = ( 0.9 * csf ) + ( 0.1 * fullNewCSF );
    if (pumpCSF) {
        var maxCSF = pumpCSF * 1.2;
        var minCSF = pumpCSF / 1.2;
        if (newCSF > maxCSF) {
            console.error("Limiting CSF to",maxCSF.toFixed(2),"(20% above pump CSF of",pumpCSF,")");
            newCSF = maxCSF;
        } else if (newCSF < minCSF) {
            console.error("Limiting CSF to",minCSF.toFixed(2),"(20% below pump CSF of",pumpCSF,")");
            newCSF = minCSF;
        } else { console.error("newCSF",newCSF,"is within 20% of",pumpCSF); }
    }
    newCSF = Math.round( newCSF * 1000 ) / 1000;
    console.error("totalMealCarbs:",totalMealCarbs,"totalDeviations:",totalDeviations,"fullNewCSF:",fullNewCSF,"newCSF:",newCSF);
    csf = newCSF;

    // reconstruct updated version of previous_autotune as autotune_output
    autotune_output = previous_autotune;
    autotune_output.basalprofile = basalprofile;
    isf_profile.sensitivities[0].sensitivity = isf;
    autotune_output.isfProfile = isf_profile;
    autotune_output.csf = csf;
    carb_ratio = isf / csf;
    carb_ratio = Math.round( carb_ratio * 1000 ) / 1000;
    autotune_output.carb_ratio = carb_ratio;

    return autotune_output;
}

exports = module.exports = generate;

// From https://gist.github.com/IceCreamYou/6ffa1b18c4c8f6aeaad2
// Returns the value at a given percentile in a sorted numeric array.
// "Linear interpolation between closest ranks" method
function percentile(arr, p) {
    if (arr.length === 0) return 0;
    if (typeof p !== 'number') throw new TypeError('p must be a number');
    if (p <= 0) return arr[0];
    if (p >= 1) return arr[arr.length - 1];

    var index = arr.length * p,
        lower = Math.floor(index),
        upper = lower + 1,
        weight = index % 1;

    if (upper >= arr.length) return arr[lower];
    return arr[lower] * (1 - weight) + arr[upper] * weight;
}

// Returns the percentile of the given value in a sorted numeric array.
function percentRank(arr, v) {
    if (typeof v !== 'number') throw new TypeError('v must be a number');
    for (var i = 0, l = arr.length; i < l; i++) {
        if (v <= arr[i]) {
            while (i < l && v === arr[i]) i++;
            if (i === 0) return 0;
            if (v !== arr[i-1]) {
                i += (v - arr[i-1]) / (arr[i] - arr[i-1]);
            }
            return i / l;
        }
    }
    return 1;
}
<|endoftext|>


<commit_before>NGApp.factory('TicketViewService', function($rootScope, $resource, $routeParams, $timeout, NotificationService, AccountService, SocketService, MainNavigationService, TicketService) {

	var service = {
		isTyping: false,
		id_support: false,
		messages: [],
		socket: SocketService.socket
	};

	service.sideInfo = { id_support: null };

	service.sideInfo.setTicket = function( id_support ){
		service.sideInfo.id_support = id_support;
		service.sideInfo.reset();
	}

	service.sideInfo.reset = function(){
		service.sideInfo.data = { id_support: service.sideInfo.id_support, messages: [], page: 0, loaded: 0, total: null, has_more: false };
		service._private = { first_load: true, current_scroll: 0, could_load: true };
		service.sideInfo.update_controller()
	};

	service.sideInfo.force_first_page = function(){
		service.sideInfo.data.loaded = 0;
		service.sideInfo.data.page = 0;
		service.sideInfo.data.total = null;
		if( !service._private ){
			service._private = { first_load: true, current_scroll: 0, could_load: true };
		} else {
			service._private.current_scroll = 0;
			service._private.first_load = true;
			service._private.could_load = true;
		}

		service.sideInfo.load();
	}

	service.sideInfo.scroll = function( action ){

		var container = $('.support-chat-contents-scroll');
		switch( action ){
			case 'begin':
				$timeout( function(){
					container.stop( true, false ).animate( { scrollTop: container[0].scrollHeight }, 0 );
					service.sideInfo.release();
				}, 300 );
				break;
			case 'current':
				service._private.current_scroll = container[0].scrollHeight;
				break;
			default:
				var position = action;
				setTimeout(function() {
					var finalScroll = container[0].scrollHeight;
					var goToScroll = finalScroll - service._private.current_scroll;
					container[0].scrollTop = goToScroll;
					service.sideInfo.release();
				}, 100 );
				break;
		}
	}

	service.sideInfo.release = function(){
		setTimeout(function() { service._private.could_load = true }, 500 );
	}

	service.sideInfo.add_message = function( message ){
		service.sideInfo.data.messages.push( message );
		service.sideInfo.data.total++;
		service.sideInfo.data.loaded++;
		service.sideInfo.update_controller();
		service.sideInfo.scroll( 'begin' );
	}

	service.sideInfo.load_ticket_page = function(){
		if( service.sideInfo.id_support ){
			MainNavigationService.link( '/ticket/' + service.sideInfo.id_support );
		}
	}

	service.sideInfo.update_controller = function(){
		$rootScope.$broadcast( 'triggerTicketInfoUpdated', service.sideInfo.data );
	}

	service.sideInfo.load = function(){

		if( service.sideInfo.id_support ){

			if( !service._private.could_load ){
				return false;
			}

			if( service.sideInfo.data.total !== null && service.sideInfo.data.loaded >= service.sideInfo.data.total ){
				return;
			}

			service._private.could_load = false;

			service.sideInfo.data.page++;

			var params = { id_support: service.sideInfo.id_support, page: service.sideInfo.data.page };

			TicketService.side_info( params, function( data ){

				service.sideInfo.scroll( 'current' );

				service.sideInfo.data.pexcard = data.pexcard;
				service.sideInfo.data.restaurant = data.restaurant;
				service.sideInfo.data.order = data.order;
				service.sideInfo.data.total = data.messages.total;

				var messages = [];
				for( x in data.messages.list ){
					if( data.messages.list[ x ].id_support_message ){
						messages.push( data.messages.list[ x ] );
					}
				}

				for( x in service.sideInfo.data.messages ){
					if( service.sideInfo.data.messages[ x ].id_support_message ){
						messages.push( service.sideInfo.data.messages[ x ] );
					}
				}
				service.sideInfo.data.messages = messages;
				service.sideInfo.data.loaded = service.sideInfo.data.messages.length;
				service.sideInfo.data.has_more = ( service.sideInfo.data.loaded >= service.sideInfo.data.total ) ? false : true;
				service.sideInfo.update_controller();
				if( service._private.first_load ){
					service.sideInfo.scroll( 'begin' );
					service._private.first_load = false;
					service.sideInfo.load_ticket_page();
				} else {
					service.sideInfo.scroll();
				}

			} );
			return true;
		}
	};

	service.setViewTicket = function(id) {
		service.scope.viewTicket = id;
		service.sideInfo.setTicket( id );
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {

		NotificationService.check();

		service.scope.viewTicket = ticket;
		service.scope.ticket = ticket;

		if (service.scope.viewTicket) {
			service.socket.emit('event.subscribe', 'ticket.' + service.scope.viewTicket);
		}
	});

	var notified  = new Array();

	$rootScope.$on('userAuth', function(e, data) {

		if (AccountService.user && AccountService.user.id_admin) {

			service.socket.on('user.preference', function(payload) {
				console.debug('Recieved preference update', payload);
				AccountService.user.prefs[payload.key] = payload.value;
				$rootScope.$apply();
			});

			if (AccountService.isSupport) {

				SocketService.listen('tickets', $rootScope)
					.on('message', function(d) {
						console.debug('Recieved chat message: ', d);

						if (notified.indexOf(d.id_support_message) > -1) {
							return;
						}

						notified.push(d.id_support_message);

						// update the chat room
						if( service.sideInfo.id_support && d.id_support ){
							service.sideInfo.force_first_page();
						}

						if (d.id_admin == AccountService.user.id_admin) {
							return;
						}

						if (d.id_support == service.scope.viewTicket) {
							//App.playAudio('support-message-recieved');
						} else {
							//App.playAudio('support-message-new');
						}

						NotificationService.notify(d.name, d.body, null, function() {
							document.getElementById('support-chat-box').focus();
						});

					});
			}

		} else {
			//service.socket.close();
			//service.socket = null;
		}
	});

	$rootScope.$watch('account.user.prefs["notification-desktop-support-all"]', function(e, value) {
		if (!service.socket) {
			return;
		}
		if (value == '1') {
			console.debug('Subscribing to all tickets');
			service.socket.emit('event.subscribe', 'tickets');
		} else {
			console.debug('Unsubscribing to all tickets');
			service.socket.emit('event.unsubscribe', 'tickets');
		}
	});

	service.send = function(message, add_as_note, callback) {
		var add_as_note = ( add_as_note ? true : false );
		var guid = App.guid();
		if( !service.sideInfo.id_support ){
			return;
		}
		TicketService.message( {
			id_support: service.sideInfo.id_support,
			body: message,
			guid: guid,
			note: add_as_note
		}, function(d) {
			for ( var x in service.sideInfo.data.messages ) {
				if ( service.sideInfo.data.messages[x].guid == guid ) {
					d.guid = guid;
					service.sideInfo.data.messages[x] = d;
					notified.push( d.id_support_message );
					break;
				}
			}
		});

		if( callback ){
			callback()
		} else {
			service.scope.$apply(function() {
				service.sideInfo.add_message( { body: message, name: AccountService.user.firstName, timestamp: new Date().getTime(), sending: true, guid: guid } );
			});
		}
	};

	service.scroll = function(instant) {
		setTimeout(function() {
			$('.support-chat-contents-scroll').stop(true,false).animate({
				scrollTop: $('.support-chat-contents-scroll')[0].scrollHeight
			}, instant ? 0 : 800);
		}, 100);
	};

	/*
	var typingTimer;

	service.typing = function(val) {
		return;
		if (!service.isTyping) {
			service.isTyping = true;
			service.websocket.send({
				type: 'ticket.typing.start'
			});

		} else {
			if (!val) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}

		if (typingTimer) {
			clearTimeout(typingTimer);
		}
		typingTimer = setTimeout(function() {
			if (service.isTyping) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}, 5000);
	};
	*/

	return service;
});
<commit_msg>Support Bar does not update to include customer/driver responses #6017<commit_after>NGApp.factory('TicketViewService', function($rootScope, $resource, $routeParams, $timeout, NotificationService, AccountService, SocketService, MainNavigationService, TicketService) {

	var service = {
		isTyping: false,
		id_support: false,
		messages: [],
		socket: SocketService.socket
	};

	service.sideInfo = { id_support: null };

	service.sideInfo.setTicket = function( id_support ){
		service.sideInfo.id_support = id_support;
		service.sideInfo.reset();
	}

	service.sideInfo.reset = function(){
		service.sideInfo.data = { id_support: service.sideInfo.id_support, messages: [], page: 0, loaded: 0, total: null, has_more: false };
		service._private = { first_load: true, current_scroll: 0, could_load: true };
		service.sideInfo.update_controller()
	};

	service.sideInfo.force_first_page = function(){
		// service.sideInfo.data.loaded = 0;
		// service.sideInfo.data.page = 0;
		// service.sideInfo.data.total = null;
		// if( !service._private ){
		// 	service._private = { first_load: true, current_scroll: 0, could_load: true };
		// } else {
		// 	service._private.current_scroll = 0;
		// 	service._private.first_load = true;
		// 	service._private.could_load = true;
		// }
		service.sideInfo.reset();
		service.sideInfo.load();
	}

	service.sideInfo.scroll = function( action ){

		var container = $('.support-chat-contents-scroll');
		switch( action ){
			case 'begin':
				$timeout( function(){
					container.stop( true, false ).animate( { scrollTop: container[0].scrollHeight }, 0 );
					service.sideInfo.release();
				}, 300 );
				break;
			case 'current':
				service._private.current_scroll = container[0].scrollHeight;
				break;
			default:
				var position = action;
				setTimeout(function() {
					var finalScroll = container[0].scrollHeight;
					var goToScroll = finalScroll - service._private.current_scroll;
					container[0].scrollTop = goToScroll;
					service.sideInfo.release();
				}, 100 );
				break;
		}
	}

	service.sideInfo.release = function(){
		setTimeout(function() { service._private.could_load = true }, 500 );
	}

	service.sideInfo.add_message = function( message ){
		service.sideInfo.data.messages.push( message );
		service.sideInfo.data.total++;
		service.sideInfo.data.loaded++;
		service.sideInfo.update_controller();
		service.sideInfo.scroll( 'begin' );
	}

	service.sideInfo.load_ticket_page = function(){
		if( service.sideInfo.id_support ){
			MainNavigationService.link( '/ticket/' + service.sideInfo.id_support );
		}
	}

	service.sideInfo.update_controller = function(){
		$rootScope.$broadcast( 'triggerTicketInfoUpdated', service.sideInfo.data );
	}

	service.sideInfo.load = function(){

		if( service.sideInfo.id_support ){

			if( !service._private.could_load ){
				return false;
			}

			if( service.sideInfo.data.total !== null && service.sideInfo.data.loaded >= service.sideInfo.data.total ){
				return;
			}

			service._private.could_load = false;

			service.sideInfo.data.page++;

			var params = { id_support: service.sideInfo.id_support, page: service.sideInfo.data.page };

			TicketService.side_info( params, function( data ){

				service.sideInfo.scroll( 'current' );

				service.sideInfo.data.pexcard = data.pexcard;
				service.sideInfo.data.restaurant = data.restaurant;
				service.sideInfo.data.order = data.order;
				service.sideInfo.data.total = data.messages.total;

				var messages = [];
				for( x in data.messages.list ){
					if( data.messages.list[ x ].id_support_message ){
						messages.push( data.messages.list[ x ] );
					}
				}

				for( x in service.sideInfo.data.messages ){
					if( service.sideInfo.data.messages[ x ].id_support_message ){
						messages.push( service.sideInfo.data.messages[ x ] );
					}
				}
				service.sideInfo.data.messages = messages;
				service.sideInfo.data.loaded = service.sideInfo.data.messages.length;
				service.sideInfo.data.has_more = ( service.sideInfo.data.loaded >= service.sideInfo.data.total ) ? false : true;
				service.sideInfo.update_controller();
				if( service._private.first_load ){
					service.sideInfo.scroll( 'begin' );
					service._private.first_load = false;
					service.sideInfo.load_ticket_page();
				} else {
					service.sideInfo.scroll();
				}

			} );
			return true;
		}
	};

	service.setViewTicket = function(id) {
		service.scope.viewTicket = id;
		service.sideInfo.setTicket( id );
	};

	$rootScope.$on('triggerViewTicket', function(e, ticket) {

		NotificationService.check();

		service.scope.viewTicket = ticket;
		service.scope.ticket = ticket;

		if (service.scope.viewTicket) {
			service.socket.emit('event.subscribe', 'ticket.' + service.scope.viewTicket);
		}
	});

	var notified  = new Array();

	$rootScope.$on('userAuth', function(e, data) {

		if (AccountService.user && AccountService.user.id_admin) {

			service.socket.on('user.preference', function(payload) {
				console.debug('Recieved preference update', payload);
				AccountService.user.prefs[payload.key] = payload.value;
				$rootScope.$apply();
			});

			if (AccountService.isSupport) {

				SocketService.listen('tickets', $rootScope)
					.on('message', function(d) {
						console.debug('Recieved chat message: ', d);

						if (notified.indexOf(d.id_support_message) > -1) {
							return;
						}

						notified.push(d.id_support_message);

						// update the chat room
						if( service.sideInfo.id_support && d.id_support ){
							service.sideInfo.force_first_page();
						}

						if (d.id_admin == AccountService.user.id_admin) {
							return;
						}

						if (d.id_support == service.scope.viewTicket) {
							//App.playAudio('support-message-recieved');
						} else {
							//App.playAudio('support-message-new');
						}

						NotificationService.notify(d.name, d.body, null, function() {
							document.getElementById('support-chat-box').focus();
						});

					});
			}

		} else {
			//service.socket.close();
			//service.socket = null;
		}
	});

	$rootScope.$watch('account.user.prefs["notification-desktop-support-all"]', function(e, value) {
		if (!service.socket) {
			return;
		}
		if (value == '1') {
			console.debug('Subscribing to all tickets');
			service.socket.emit('event.subscribe', 'tickets');
		} else {
			console.debug('Unsubscribing to all tickets');
			service.socket.emit('event.unsubscribe', 'tickets');
		}
	});

	service.send = function(message, add_as_note, callback) {
		var add_as_note = ( add_as_note ? true : false );
		var guid = App.guid();
		if( !service.sideInfo.id_support ){
			return;
		}
		TicketService.message( {
			id_support: service.sideInfo.id_support,
			body: message,
			guid: guid,
			note: add_as_note
		}, function(d) {
			for ( var x in service.sideInfo.data.messages ) {
				if ( service.sideInfo.data.messages[x].guid == guid ) {
					d.guid = guid;
					service.sideInfo.data.messages[x] = d;
					notified.push( d.id_support_message );
					break;
				}
			}
		});

		if( callback ){
			callback()
		} else {
			service.scope.$apply(function() {
				service.sideInfo.add_message( { body: message, name: AccountService.user.firstName, timestamp: new Date().getTime(), sending: true, guid: guid } );
			});
		}
	};

	service.scroll = function(instant) {
		setTimeout(function() {
			$('.support-chat-contents-scroll').stop(true,false).animate({
				scrollTop: $('.support-chat-contents-scroll')[0].scrollHeight
			}, instant ? 0 : 800);
		}, 100);
	};

	/*
	var typingTimer;

	service.typing = function(val) {
		return;
		if (!service.isTyping) {
			service.isTyping = true;
			service.websocket.send({
				type: 'ticket.typing.start'
			});

		} else {
			if (!val) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}

		if (typingTimer) {
			clearTimeout(typingTimer);
		}
		typingTimer = setTimeout(function() {
			if (service.isTyping) {
				service.isTyping = false;
				service.websocket.send({
					type: 'ticket.typing.stop'
				});
			}
		}, 5000);
	};
	*/

	return service;
});
<|endoftext|>