<commit_before>// @flow

const R = require('ramda');
const esClient = require('../../clients/esClient');
const sqlClient = require('../../clients/sqlClient');
const {
  ifNotAdmin,
  inClauseOr,
  isPatchEmpty,
  prepare,
  query,
  whereAnd,
} = require('../../util/db');
const Sql = require('./sql');

/* ::

import type {ResolversObj} from '../';

*/

const deployTypeToString = R.cond([
  [R.equals('BRANCH'), R.toLower],
  [R.equals('PULLREQUEST'), R.toLower],
  [R.equals('PROMOTE'), R.toLower],
  [R.T, R.identity],
]);

const envTypeToString = R.cond([
  [R.equals('PRODUCTION'), R.toLower],
  [R.equals('DEVELOPMENT'), R.toLower],
  [R.T, R.identity],
]);

const getEnvironmentByName = async (
  root,
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const str = `
    SELECT *
    FROM environment
    WHERE name = :name AND
    project = :project
    ${ifNotAdmin(
    role,
    `AND (${inClauseOr([
      ['customer', customers],
      ['project.id', projects],
    ])})`,
  )}
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep(args));

  return rows[0];
};

const getEnvironmentsByProjectId = async (
  { id: pid },
  unformattedArgs,
  {
    credentials: {
      role,
      permissions: { projects },
    },
  },
) => {
  const args = R.compose(R.over(R.lensProp('type'), envTypeToString))(
    unformattedArgs,
  );

  if (role !== 'admin' && !R.contains(pid, projects)) {
    throw new Error('Unauthorized');
  }

  const prep = prepare(
    sqlClient,
    `
      SELECT *
      FROM environment e
      WHERE e.project = :pid
      ${args.includeDeleted ? '' : 'AND deleted = "0000-00-00 00:00:00"'}
      ${args.type ? 'AND e.environment_type = :type' : ''}
    `,
  );

  const rows = await query(sqlClient, prep({ pid, type: args.type }));

  return rows;
};

const getEnvironmentByDeploymentId = async (
  { id: deployment_id },
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const prep = prepare(
    sqlClient,
    `SELECT
        e.*
      FROM deployment d
      JOIN environment e on d.environment = e.id
      JOIN project p ON e.project = p.id
      WHERE d.id = :deployment_id
      ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['p.customer', customers], ['p.id', projects]])})`,
  )}
      LIMIT 1
    `,
  );

  const rows = await query(sqlClient, prep({ deployment_id }));

  return rows ? rows[0] : null;
};

const getEnvironmentByTaskId = async (
  { id: task_id },
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const prep = prepare(
    sqlClient,
    `SELECT
        e.*
      FROM task t
      JOIN environment e on t.environment = e.id
      JOIN project p ON e.project = p.id
      WHERE t.id = :task_id
      ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['p.customer', customers], ['p.id', projects]])})`,
  )}
      LIMIT 1
    `,
  );

  const rows = await query(sqlClient, prep({ task_id }));

  return rows ? rows[0] : null;
};

const getEnvironmentStorageByEnvironmentId = async (
  { id: eid },
  args,
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const prep = prepare(
    sqlClient,
    `
      SELECT *
      FROM environment_storage es
      WHERE es.environment = :eid
    `,
  );

  const rows = await query(sqlClient, prep({ eid }));

  return rows;
};

const getEnvironmentStorageMonthByEnvironmentId = async ({ id: eid }, args) => {
  const str = `
    SELECT
      SUM(bytes_used) as bytes_used, max(DATE_FORMAT(updated, '%Y-%m')) as month
    FROM
      environment_storage
    WHERE
      environment = :eid
      AND YEAR(updated) = YEAR(STR_TO_DATE(:month, '%Y-%m'))
      AND MONTH(updated) = MONTH(STR_TO_DATE(:month, '%Y-%m'))
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep({ eid, month: args.month }));

  return rows[0];
};

const getEnvironmentHoursMonthByEnvironmentId = async ({ id: eid }, args) => {
  const str = `
    SELECT
      e.created, e.deleted
    FROM
      environment e
    WHERE
      e.id = :eid
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep({ eid }));

  const { created, deleted } = rows[0];

  const created_date = new Date(created);
  const deleted_date = new Date(deleted);

  const now = new Date();

  // Generate date object of the requested month, but with the first day, hour, minute, seconds and milliseconds
  const interested_month_start = new Date(args.month) || new Date();
  interested_month_start.setDate(1);
  interested_month_start.setHours(0);
  interested_month_start.setMinutes(0);
  interested_month_start.setSeconds(0);
  interested_month_start.setMilliseconds(0);

  if (interested_month_start > now) {
    throw new Error("Can't predict the future, yet.");
  }

  // Generate Date Variable with the month we are interested in plus one month
  let interested_month_end = new Date(interested_month_start);
  interested_month_end.setMonth(interested_month_start.getMonth() + 1);

  // If the the the interested month end is in the future, we use the current time for real time cost calculations
  if (interested_month_end > now) {
    interested_month_end = now;
  }

  // calculate the month in format `YYYY-MM`. getMonth() does not return with a leading zero and starts its index at 0 as well.
  const month_leading_zero =
    interested_month_start.getMonth() + 1 < 10
      ? `0${interested_month_start.getMonth() + 1}`
      : interested_month_start.getMonth() + 1;
  const month = `${interested_month_start.getFullYear()}-${month_leading_zero}`;

  // Created Date is created after the interested month: Ran for 0 hours in the requested month
  if (created_date > interested_month_end) {
    return { month, hours: 0 };
  }

  // Environment was deleted before the month we are interested in: Ran for 0 hours in the requested month
  if (
    deleted_date < interested_month_start &&
    deleted_date !== '0000-00-00 00:00:00'
  ) {
    return { month, hours: 0 };
  }

  let date_from;
  let date_to;

  if (created_date >= interested_month_start) {
    // Environment was created within the interested month
    date_from = created_date;
  } else {
    // Environment was created before the interested month
    date_from = interested_month_start;
  }

  if (
    deleted === '0000-00-00 00:00:00' ||
    deleted_date > interested_month_end
  ) {
    // Environment is not deleted yet or was deleted after the interested month
    date_to = interested_month_end;
  } else {
    // Environment was deleted in the interested month
    date_to = deleted_date;
  }

  const hours = Math.ceil(Math.abs(date_to - date_from) / 36e5);
  return { month, hours };
};

const getEnvironmentHitsMonthByEnvironmentId = async (
  { openshiftProjectName },
  args,
) => {
  const interested_month = args.month ? new Date(args.month) : new Date();
  const now = new Date();
  const interested_month_relative =
    interested_month.getMonth() - now.getMonth();
  // Elasticsearch needs relative numbers with + or - in front. The - already exists, so we add the + if it's a positive number.
  const interested_month_relative_plus_sign =
    (interested_month_relative < 0 ? '' : '+') + interested_month_relative;

  try {
    const result = await esClient.count({
      index: `router-logs-${openshiftProjectName}-*`,
      body: {
        query: {
          bool: {
            must: [
              {
                range: {
                  '@timestamp': {
                    gte: `now${interested_month_relative_plus_sign}M/M`,
                    lte: `now${interested_month_relative_plus_sign}M/M`,
                  },
                },
              },
            ],
            must_not: [
              {
                match_phrase: {
                  request_header_useragent: {
                    query: 'StatusCake',
                  },
                },
              },
            ],
          },
        },
      },
    });

    const response = {
      total: result.count,
    };
    return response;
  } catch (e) {
    if (
      e.body.error.type &&
      (e.body.error.type === 'index_not_found_exception' || e.body.error.type === 'security_exception')
    ) {
      return { total: 0 };
    }
    throw e;
  }
};

const getEnvironmentServicesByEnvironmentId = async (
  { id: eid },
  args,
  { credentials: { role } },
) => {
  const rows = await query(sqlClient, Sql.selectServicesByEnvironmentId(eid));

  return rows;
};

const getEnvironmentByOpenshiftProjectName = async (
  root,
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const str = `
    SELECT
      e.*
    FROM
      environment e
      JOIN project p ON e.project = p.id
      JOIN customer c ON p.customer = c.id
    WHERE e.openshift_project_name = :openshift_project_name
    ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['c.id', customers], ['p.id', projects]])})`,
  )}
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep(args));

  return rows[0];
};

const addOrUpdateEnvironment = async (
  root,
  { input: unformattedInput },
  {
    credentials: {
      role,
      permissions: { projects },
    },
  },
) => {
  const input = R.compose(
    R.over(R.lensProp('environmentType'), envTypeToString),
    R.over(R.lensProp('deployType'), deployTypeToString),
  )(unformattedInput);

  const pid = input.project.toString();

  if (role !== 'admin' && !R.contains(pid, projects)) {
    throw new Error('Project creation unauthorized.');
  }
  const prep = prepare(
    sqlClient,
    `
      CALL CreateOrUpdateEnvironment(
        :id,
        :name,
        :project,
        :deploy_type,
        :environment_type,
        :openshift_project_name
      );
    `,
  );

  const rows = await query(sqlClient, prep(input));
  const environment = R.path([0, 0], rows);

  return environment;
};

const addOrUpdateEnvironmentStorage = async (
  root,
  { input },
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('EnvironmentStorage creation unauthorized.');
  }
  const prep = prepare(
    sqlClient,
    `
      CALL CreateOrUpdateEnvironmentStorage(
        :environment,
        :persistent_storage_claim,
        :bytes_used
      );
    `,
  );

  const rows = await query(sqlClient, prep(input));
  const environment = R.path([0, 0], rows);

  return environment;
};

// const getEnvironmentByEnvironmentStorageId = async (
//   { id: esid },
//   args,
//   { credentials: { role } },
// ) => {
//   if (role !== 'admin') {
//     throw new Error('Unauthorized');
//   }
//   const prep = prepare(
//     sqlClient,
//     `
//       SELECT e.*
//       FROM environment_storage es
//       JOIN environment e ON es.environment = e.id
//       WHERE es.id = :esid
//     `,
//   );

//   const rows = await query(sqlClient, prep({ esid }));

//   return rows ? rows[0] : null;
// };

const deleteEnvironment = async (
  root,
  { input },
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const prep = prepare(sqlClient, 'CALL DeleteEnvironment(:name, :project)');
  await query(sqlClient, prep(input));

  // TODO: maybe check rows for changed result
  return 'success';
};

const updateEnvironment = async (
  root,
  { input: unformattedInput },
  { credentials: { role } },
) => {
  const input = R.compose(
    R.over(R.lensPath(['patch', 'environmentType']), envTypeToString),
    R.over(R.lensPath(['patch', 'deployType']), deployTypeToString),
  )(unformattedInput);

  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  if (isPatchEmpty(input)) {
    throw new Error('input.patch requires at least 1 attribute');
  }

  const id = input.id;
  await query(sqlClient, Sql.updateEnvironment(input));

  const rows = await query(sqlClient, Sql.selectEnvironmentById(id));

  return R.prop(0, rows);
};

const getAllEnvironments = async (
  root,
  unformattedArgs,
  { credentials: { role } },
) => {
  const args = R.compose(R.over(R.lensProp('type'), envTypeToString))(
    unformattedArgs,
  );

  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const where = whereAnd([
    args.createdAfter ? 'created >= :created_after' : '',
    args.type ? 'environment_type = :type' : '',
    'deleted = "0000-00-00 00:00:00"',
  ]);

  const prep = prepare(sqlClient, `SELECT * FROM environment ${where}`);
  const rows = await query(sqlClient, prep(args));
  return rows;
};

const deleteAllEnvironments = async (root, args, { credentials: { role } }) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized.');
  }

  await query(sqlClient, Sql.truncateEnvironment());

  // TODO: Check rows for success
  return 'success';
};

const setEnvironmentServices = async (
  root,
  { input: { environment, services } },
  { credentials: { role, permissions: { customers, projects } } },
) => {
  if (role !== 'admin') {
    const rows = await query(
      sqlClient,
      Sql.selectPermsForEnvironment(environment),
    );

    if (
      !R.contains(R.path(['0', 'pid'], rows), projects) &&
      !R.contains(R.path(['0', 'cid'], rows), customers)
    ) {
      throw new Error('Unauthorized.');
    }
  }

  await query(sqlClient, Sql.deleteServices(environment));

  for (const service of services) {
    await query(sqlClient, Sql.insertService(environment, service));
  }

  return query(sqlClient, Sql.selectServicesByEnvironmentId(environment));
};

const Resolvers /* : ResolversObj */ = {
  addOrUpdateEnvironment,
  addOrUpdateEnvironmentStorage,
  getEnvironmentByName,
  getEnvironmentByOpenshiftProjectName,
  getEnvironmentHoursMonthByEnvironmentId,
  getEnvironmentStorageByEnvironmentId,
  getEnvironmentStorageMonthByEnvironmentId,
  getEnvironmentHitsMonthByEnvironmentId,
  getEnvironmentByDeploymentId,
  getEnvironmentByTaskId,
  getEnvironmentServicesByEnvironmentId,
  setEnvironmentServices,
  deleteEnvironment,
  getEnvironmentsByProjectId,
  updateEnvironment,
  getAllEnvironments,
  deleteAllEnvironments,
};

module.exports = Resolvers;
<commit_msg>date calculator had an issue with year changes, using elasticsearch internal calculator now<commit_after>// @flow

const R = require('ramda');
const esClient = require('../../clients/esClient');
const sqlClient = require('../../clients/sqlClient');
const {
  ifNotAdmin,
  inClauseOr,
  isPatchEmpty,
  prepare,
  query,
  whereAnd,
} = require('../../util/db');
const Sql = require('./sql');

/* ::

import type {ResolversObj} from '../';

*/

const deployTypeToString = R.cond([
  [R.equals('BRANCH'), R.toLower],
  [R.equals('PULLREQUEST'), R.toLower],
  [R.equals('PROMOTE'), R.toLower],
  [R.T, R.identity],
]);

const envTypeToString = R.cond([
  [R.equals('PRODUCTION'), R.toLower],
  [R.equals('DEVELOPMENT'), R.toLower],
  [R.T, R.identity],
]);

const getEnvironmentByName = async (
  root,
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const str = `
    SELECT *
    FROM environment
    WHERE name = :name AND
    project = :project
    ${ifNotAdmin(
    role,
    `AND (${inClauseOr([
      ['customer', customers],
      ['project.id', projects],
    ])})`,
  )}
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep(args));

  return rows[0];
};

const getEnvironmentsByProjectId = async (
  { id: pid },
  unformattedArgs,
  {
    credentials: {
      role,
      permissions: { projects },
    },
  },
) => {
  const args = R.compose(R.over(R.lensProp('type'), envTypeToString))(
    unformattedArgs,
  );

  if (role !== 'admin' && !R.contains(pid, projects)) {
    throw new Error('Unauthorized');
  }

  const prep = prepare(
    sqlClient,
    `
      SELECT *
      FROM environment e
      WHERE e.project = :pid
      ${args.includeDeleted ? '' : 'AND deleted = "0000-00-00 00:00:00"'}
      ${args.type ? 'AND e.environment_type = :type' : ''}
    `,
  );

  const rows = await query(sqlClient, prep({ pid, type: args.type }));

  return rows;
};

const getEnvironmentByDeploymentId = async (
  { id: deployment_id },
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const prep = prepare(
    sqlClient,
    `SELECT
        e.*
      FROM deployment d
      JOIN environment e on d.environment = e.id
      JOIN project p ON e.project = p.id
      WHERE d.id = :deployment_id
      ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['p.customer', customers], ['p.id', projects]])})`,
  )}
      LIMIT 1
    `,
  );

  const rows = await query(sqlClient, prep({ deployment_id }));

  return rows ? rows[0] : null;
};

const getEnvironmentByTaskId = async (
  { id: task_id },
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const prep = prepare(
    sqlClient,
    `SELECT
        e.*
      FROM task t
      JOIN environment e on t.environment = e.id
      JOIN project p ON e.project = p.id
      WHERE t.id = :task_id
      ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['p.customer', customers], ['p.id', projects]])})`,
  )}
      LIMIT 1
    `,
  );

  const rows = await query(sqlClient, prep({ task_id }));

  return rows ? rows[0] : null;
};

const getEnvironmentStorageByEnvironmentId = async (
  { id: eid },
  args,
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const prep = prepare(
    sqlClient,
    `
      SELECT *
      FROM environment_storage es
      WHERE es.environment = :eid
    `,
  );

  const rows = await query(sqlClient, prep({ eid }));

  return rows;
};

const getEnvironmentStorageMonthByEnvironmentId = async ({ id: eid }, args) => {
  const str = `
    SELECT
      SUM(bytes_used) as bytes_used, max(DATE_FORMAT(updated, '%Y-%m')) as month
    FROM
      environment_storage
    WHERE
      environment = :eid
      AND YEAR(updated) = YEAR(STR_TO_DATE(:month, '%Y-%m'))
      AND MONTH(updated) = MONTH(STR_TO_DATE(:month, '%Y-%m'))
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep({ eid, month: args.month }));

  return rows[0];
};

const getEnvironmentHoursMonthByEnvironmentId = async ({ id: eid }, args) => {
  const str = `
    SELECT
      e.created, e.deleted
    FROM
      environment e
    WHERE
      e.id = :eid
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep({ eid }));

  const { created, deleted } = rows[0];

  const created_date = new Date(created);
  const deleted_date = new Date(deleted);

  const now = new Date();

  // Generate date object of the requested month, but with the first day, hour, minute, seconds and milliseconds
  const interested_month_start = new Date(args.month) || new Date();
  interested_month_start.setDate(1);
  interested_month_start.setHours(0);
  interested_month_start.setMinutes(0);
  interested_month_start.setSeconds(0);
  interested_month_start.setMilliseconds(0);

  if (interested_month_start > now) {
    throw new Error("Can't predict the future, yet.");
  }

  // Generate Date Variable with the month we are interested in plus one month
  let interested_month_end = new Date(interested_month_start);
  interested_month_end.setMonth(interested_month_start.getMonth() + 1);

  // If the the the interested month end is in the future, we use the current time for real time cost calculations
  if (interested_month_end > now) {
    interested_month_end = now;
  }

  // calculate the month in format `YYYY-MM`. getMonth() does not return with a leading zero and starts its index at 0 as well.
  const month_leading_zero =
    interested_month_start.getMonth() + 1 < 10
      ? `0${interested_month_start.getMonth() + 1}`
      : interested_month_start.getMonth() + 1;
  const month = `${interested_month_start.getFullYear()}-${month_leading_zero}`;

  // Created Date is created after the interested month: Ran for 0 hours in the requested month
  if (created_date > interested_month_end) {
    return { month, hours: 0 };
  }

  // Environment was deleted before the month we are interested in: Ran for 0 hours in the requested month
  if (
    deleted_date < interested_month_start &&
    deleted_date !== '0000-00-00 00:00:00'
  ) {
    return { month, hours: 0 };
  }

  let date_from;
  let date_to;

  if (created_date >= interested_month_start) {
    // Environment was created within the interested month
    date_from = created_date;
  } else {
    // Environment was created before the interested month
    date_from = interested_month_start;
  }

  if (
    deleted === '0000-00-00 00:00:00' ||
    deleted_date > interested_month_end
  ) {
    // Environment is not deleted yet or was deleted after the interested month
    date_to = interested_month_end;
  } else {
    // Environment was deleted in the interested month
    date_to = deleted_date;
  }

  const hours = Math.ceil(Math.abs(date_to - date_from) / 36e5);
  return { month, hours };
};

const getEnvironmentHitsMonthByEnvironmentId = async (
  { openshiftProjectName },
  args,
) => {
  const interested_date = args.month ? new Date(args.month) : new Date();
  try {
    const result = await esClient.count({
      index: `router-logs-${openshiftProjectName}-*`,
      body: {
        query: {
          bool: {
            must: [
              {
                range: {
                  '@timestamp': {
                    gte: `${interested_date.getFullYear()}-${interested_date.getMonth()}||/M`,
                    lte: `${interested_date.getFullYear()}-${interested_date.getMonth()}||/M`,
                  },
                },
              },
            ],
            must_not: [
              {
                match_phrase: {
                  request_header_useragent: {
                    query: 'StatusCake',
                  },
                },
              },
            ],
          },
        },
      },
    });

    const response = {
      total: result.count,
    };
    return response;
  } catch (e) {
    if (
      e.body.error.type &&
      (e.body.error.type === 'index_not_found_exception' || e.body.error.type === 'security_exception')
    ) {
      return { total: 0 };
    }
    throw e;
  }
};

const getEnvironmentServicesByEnvironmentId = async (
  { id: eid },
  args,
  { credentials: { role } },
) => {
  const rows = await query(sqlClient, Sql.selectServicesByEnvironmentId(eid));

  return rows;
};

const getEnvironmentByOpenshiftProjectName = async (
  root,
  args,
  {
    credentials: {
      role,
      permissions: { customers, projects },
    },
  },
) => {
  const str = `
    SELECT
      e.*
    FROM
      environment e
      JOIN project p ON e.project = p.id
      JOIN customer c ON p.customer = c.id
    WHERE e.openshift_project_name = :openshift_project_name
    ${ifNotAdmin(
    role,
    `AND (${inClauseOr([['c.id', customers], ['p.id', projects]])})`,
  )}
  `;

  const prep = prepare(sqlClient, str);

  const rows = await query(sqlClient, prep(args));

  return rows[0];
};

const addOrUpdateEnvironment = async (
  root,
  { input: unformattedInput },
  {
    credentials: {
      role,
      permissions: { projects },
    },
  },
) => {
  const input = R.compose(
    R.over(R.lensProp('environmentType'), envTypeToString),
    R.over(R.lensProp('deployType'), deployTypeToString),
  )(unformattedInput);

  const pid = input.project.toString();

  if (role !== 'admin' && !R.contains(pid, projects)) {
    throw new Error('Project creation unauthorized.');
  }
  const prep = prepare(
    sqlClient,
    `
      CALL CreateOrUpdateEnvironment(
        :id,
        :name,
        :project,
        :deploy_type,
        :environment_type,
        :openshift_project_name
      );
    `,
  );

  const rows = await query(sqlClient, prep(input));
  const environment = R.path([0, 0], rows);

  return environment;
};

const addOrUpdateEnvironmentStorage = async (
  root,
  { input },
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('EnvironmentStorage creation unauthorized.');
  }
  const prep = prepare(
    sqlClient,
    `
      CALL CreateOrUpdateEnvironmentStorage(
        :environment,
        :persistent_storage_claim,
        :bytes_used
      );
    `,
  );

  const rows = await query(sqlClient, prep(input));
  const environment = R.path([0, 0], rows);

  return environment;
};

// const getEnvironmentByEnvironmentStorageId = async (
//   { id: esid },
//   args,
//   { credentials: { role } },
// ) => {
//   if (role !== 'admin') {
//     throw new Error('Unauthorized');
//   }
//   const prep = prepare(
//     sqlClient,
//     `
//       SELECT e.*
//       FROM environment_storage es
//       JOIN environment e ON es.environment = e.id
//       WHERE es.id = :esid
//     `,
//   );

//   const rows = await query(sqlClient, prep({ esid }));

//   return rows ? rows[0] : null;
// };

const deleteEnvironment = async (
  root,
  { input },
  { credentials: { role } },
) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const prep = prepare(sqlClient, 'CALL DeleteEnvironment(:name, :project)');
  await query(sqlClient, prep(input));

  // TODO: maybe check rows for changed result
  return 'success';
};

const updateEnvironment = async (
  root,
  { input: unformattedInput },
  { credentials: { role } },
) => {
  const input = R.compose(
    R.over(R.lensPath(['patch', 'environmentType']), envTypeToString),
    R.over(R.lensPath(['patch', 'deployType']), deployTypeToString),
  )(unformattedInput);

  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  if (isPatchEmpty(input)) {
    throw new Error('input.patch requires at least 1 attribute');
  }

  const id = input.id;
  await query(sqlClient, Sql.updateEnvironment(input));

  const rows = await query(sqlClient, Sql.selectEnvironmentById(id));

  return R.prop(0, rows);
};

const getAllEnvironments = async (
  root,
  unformattedArgs,
  { credentials: { role } },
) => {
  const args = R.compose(R.over(R.lensProp('type'), envTypeToString))(
    unformattedArgs,
  );

  if (role !== 'admin') {
    throw new Error('Unauthorized');
  }

  const where = whereAnd([
    args.createdAfter ? 'created >= :created_after' : '',
    args.type ? 'environment_type = :type' : '',
    'deleted = "0000-00-00 00:00:00"',
  ]);

  const prep = prepare(sqlClient, `SELECT * FROM environment ${where}`);
  const rows = await query(sqlClient, prep(args));
  return rows;
};

const deleteAllEnvironments = async (root, args, { credentials: { role } }) => {
  if (role !== 'admin') {
    throw new Error('Unauthorized.');
  }

  await query(sqlClient, Sql.truncateEnvironment());

  // TODO: Check rows for success
  return 'success';
};

const setEnvironmentServices = async (
  root,
  { input: { environment, services } },
  { credentials: { role, permissions: { customers, projects } } },
) => {
  if (role !== 'admin') {
    const rows = await query(
      sqlClient,
      Sql.selectPermsForEnvironment(environment),
    );

    if (
      !R.contains(R.path(['0', 'pid'], rows), projects) &&
      !R.contains(R.path(['0', 'cid'], rows), customers)
    ) {
      throw new Error('Unauthorized.');
    }
  }

  await query(sqlClient, Sql.deleteServices(environment));

  for (const service of services) {
    await query(sqlClient, Sql.insertService(environment, service));
  }

  return query(sqlClient, Sql.selectServicesByEnvironmentId(environment));
};

const Resolvers /* : ResolversObj */ = {
  addOrUpdateEnvironment,
  addOrUpdateEnvironmentStorage,
  getEnvironmentByName,
  getEnvironmentByOpenshiftProjectName,
  getEnvironmentHoursMonthByEnvironmentId,
  getEnvironmentStorageByEnvironmentId,
  getEnvironmentStorageMonthByEnvironmentId,
  getEnvironmentHitsMonthByEnvironmentId,
  getEnvironmentByDeploymentId,
  getEnvironmentByTaskId,
  getEnvironmentServicesByEnvironmentId,
  setEnvironmentServices,
  deleteEnvironment,
  getEnvironmentsByProjectId,
  updateEnvironment,
  getAllEnvironments,
  deleteAllEnvironments,
};

module.exports = Resolvers;
<|endoftext|>


<commit_before>var babel = require('babel-core');
var glob = require('glob');
var fsExtra = require('fs-extra');
var path = require('path');
var fs = require('fs');

var SRC_DIR = './src';
var DST_DIR = './lib';
var CP_ONLY = [SRC_DIR + '/model/inheritModel/inheritModelEs6.js'];
var BABEL_OPT = {
  presets: [],
  sourceMaps: 'inline',
  plugins: [
    "transform-decorators-legacy",
    "transform-class-properties",

    "transform-es2015-template-literals",
    "transform-es2015-literals",
    "transform-es2015-function-name",
    "transform-es2015-arrow-functions",
    "transform-es2015-block-scoped-functions",
    ["transform-es2015-classes", {
      loose: true
    }],
    "transform-es2015-shorthand-properties",
    "transform-es2015-duplicate-keys",
    "transform-es2015-computed-properties",
    "transform-es2015-sticky-regex",
    "transform-es2015-unicode-regex",
    "check-es2015-constants",
    "transform-es2015-spread",
    "transform-es2015-parameters",
    "transform-es2015-destructuring",
    "transform-es2015-block-scoping",
    "transform-es2015-typeof-symbol",
    "transform-es2015-modules-commonjs",
    "transform-runtime"
  ]
};

// Clean the lib fir so that removed files don't linger.
fsExtra.removeSync(DST_DIR);

var src = glob.sync(SRC_DIR + '/**/*.js');

for (var i = 0; i < src.length; ++i) {
  var dst = DST_DIR + src[i].substring(SRC_DIR.length);
  var code;

  if (CP_ONLY.indexOf(src[i]) !== -1) {
    code = fs.readFileSync(src[i]);
  } else {
    code = babel.transformFileSync(src[i], BABEL_OPT).code;
  }

  fsExtra.ensureDirSync(path.dirname(dst));
  fs.writeFileSync(dst, code);
}

try {
  var child_process = require('child_process');
  var process = require('process');
} catch (e) {
  // node is < v5, don't bother with TypeScript.
}

if (process && process.version >= 'v5') {
  // sanity-check the TypeScript definitions:
  child_process.execSync(
    path.join(__dirname, "node_modules", ".bin", "tsc"),
    { cwd: __dirname }
  );
}
<commit_msg>Check before invoking tsc<commit_after>var babel = require('babel-core');
var glob = require('glob');
var fsExtra = require('fs-extra');
var path = require('path');
var fs = require('fs');

var SRC_DIR = './src';
var DST_DIR = './lib';
var CP_ONLY = [SRC_DIR + '/model/inheritModel/inheritModelEs6.js'];
var BABEL_OPT = {
  presets: [],
  sourceMaps: 'inline',
  plugins: [
    "transform-decorators-legacy",
    "transform-class-properties",

    "transform-es2015-template-literals",
    "transform-es2015-literals",
    "transform-es2015-function-name",
    "transform-es2015-arrow-functions",
    "transform-es2015-block-scoped-functions",
    ["transform-es2015-classes", {
      loose: true
    }],
    "transform-es2015-shorthand-properties",
    "transform-es2015-duplicate-keys",
    "transform-es2015-computed-properties",
    "transform-es2015-sticky-regex",
    "transform-es2015-unicode-regex",
    "check-es2015-constants",
    "transform-es2015-spread",
    "transform-es2015-parameters",
    "transform-es2015-destructuring",
    "transform-es2015-block-scoping",
    "transform-es2015-typeof-symbol",
    "transform-es2015-modules-commonjs",
    "transform-runtime"
  ]
};

// Clean the lib fir so that removed files don't linger.
fsExtra.removeSync(DST_DIR);

var src = glob.sync(SRC_DIR + '/**/*.js');

for (var i = 0; i < src.length; ++i) {
  var dst = DST_DIR + src[i].substring(SRC_DIR.length);
  var code;

  if (CP_ONLY.indexOf(src[i]) !== -1) {
    code = fs.readFileSync(src[i]);
  } else {
    code = babel.transformFileSync(src[i], BABEL_OPT).code;
  }

  fsExtra.ensureDirSync(path.dirname(dst));
  fs.writeFileSync(dst, code);
}

try {
  var child_process = require('child_process');
  var process = require('process');
} catch (e) {
  // node is < v5, don't bother with TypeScript.
}

// sanity-check the TypeScript definitions, if possible:
if (process && process.version >= 'v5') {
  var tsc = path.join(__dirname, "node_modules", ".bin", "tsc")
  if (fs.existsSync(tsc)) {
    child_process.execSync(tsc, { cwd: __dirname });
  } else {
    console.log("The typescript compiler is missing. Run `npm install`.")
  }
}
<|endoftext|>


<commit_before>
/*

  Utils.js

*/

var fs        = require("fs"),
    url       = require("url"),
    path      = require("path"),
    chokidar  = require("chokidar"),
    Utils;

module.exports = Utils = {};

/*

  function makePathAbsolute

*/

Utils.makePathAbsolute = function(p) {

  if (path.isAbsolute(p))
    return p;
  else
    return path.resolve(process.cwd(), p || "");

}

/*

  function isIndexFile

*/

Utils.isIndexFile = function(file) {
  return /index[^\/]*$/.test(file.name);
}

Utils.uniqueExtensions = function(p) {
  return Utils.readDirectory(p).reduce(function(arr, file) {
    if (-1 === arr.indexOf(file.ext)) arr.push(file.ext);
    return arr;
  }, []);
};

/*

  function mapFiles

  Note that we remove leading "." from file extension

*/

Utils.mapFiles = function(p, options) {

  var files, i, indices, results = [];
  options = options || {};

  // Make path absolute before call (for comparison after)
  p = Utils.makePathAbsolute(p);

  files = Utils.readDirectory(p, options.recursive);

  // Sort in reverse order so that directory calls come last. Then move "index" to end.
  if (options.sort) {
    files.sort(function(a, b) { return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0; }).reverse();
    i = files.length;
    while (i-- > 0)
      if (Utils.isIndexFile(files[i]))
        Array.prototype.push.apply(files, files.splice(i, 1));
  }

  // Remove subdirectory files if index.* is encountered
  if (options.bundleFolders) {

    indices = [];

    // Filter out index files (outside of master directory)
    i = files.length;
    while (i-- > 0) {
      if (Utils.isIndexFile(files[i]) && (p !== files[i].dir))
        Array.prototype.push.apply(indices, files.splice(i, 1));
    }

    // Remove indices that are subdirectories of each other
    i = indices.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++) {
        if (i !== j && 0 === indices[i].path.indexOf(indices[j].dir)) {
          indices.splice(i, 1);
          break;
        }
      }

    // Remove files in subdirectories of indices
    i = files.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++)
        if (0 === files[i].path.indexOf(indices[j].dir)) {
          files.splice(i, 1);
          break;
        }

    // Denote indices as bundles
    indices.forEach(function(file) {
      file.bundle = true;
      file.ignored = [
        path.relative(process.cwd(), path.join(file.dir, "*")),
        path.relative(process.cwd(), file.dir + "." + options.ext)
      ];
    });

    // Rejoin indices back into files
    files = files.concat(indices);

  }

  files.forEach(function(file) {
    if (!options.filter || options.filter.indexOf(file.ext) > -1) {
      file.ext = file.ext.replace(/^\./, "");
      file.basePath = p;
      file.folder = path.relative(p, file.path.replace(new RegExp(file.base + "$"), ""));
      results.push(file);
    }
  });

  return results;

}

/*

  function makeRoutes

*/

Utils.makeRoutes = function(route, file, options) {

  var base,
      routes,
      ext,
      options = options || {};

  // !!! WHAT TO DO ABOUT EXTENSIONLESS FILES?
  ext = options.type || file.ext;
  ext = ("undefined" == typeof ext) ? "" : ext.replace(/^\./, "");
  base = (url.resolve((route + "/").replace(/\/\/$/, "/"), file.folder) + "/").replace(/\/\/$/, "/");

  // Wildcard directories
  if ("html" === ext && options.query) {
    // If name starts with @, look for parent directory;
    if ("@" === file.name[0]) base = base.split("/").slice(0, -1).join("/")
    return [base + "/:slug"];
  }

  // Add file and default extension
  routes = [url.resolve(base, file.name + "." + ext)];

  // HTML files are special: not only can they be accessed sans extension, if they are named
  // "index", we allow access via a folder.
  if ("html" === ext) {
    routes.push(url.resolve(base, file.name));
    if (Utils.isIndexFile(file)) routes.push(base);
  }

  return routes;

}

/*

  function readDirectory

*/

Utils.readDirectory = function(p, recursive) {

  var results = [];

  // Set defaults
  if ("undefined" == typeof recursive) recursive = true;
  p = Utils.makePathAbsolute(p);

  // If directory doesn't exist, return nothing
  try {
    fs.lstatSync(p);
  } catch (err) {
    return results;
  }

  // Read in files
  fs.readdirSync(p).forEach(function(file) {

    var stats, parsed;

    // Read file and stats
    file = path.join(p, file);
    stats = fs.lstatSync(file);

    // Recursively walk directory, or add file
    if (stats.isDirectory()) {
      if (recursive)
        results = results.concat(Utils.readDirectory(file, true))
    } else {
      parsed = path.parse(file);
      parsed.path = file;
      results.push(parsed);
    }

  });

  return results;

}

/*

 function readFileHead

 Reads a limited number of characters from a file.

*/

Utils.readFileHead = function(path, chars) {

  var buffer = new Buffer(chars),
      file   = fs.openSync(path, "r"),
      str,
      len;

  // Read in file
  len = fs.readSync(file, buffer, 0, chars, 0);

  // Convert to lines, and discard any fragments
  // (so that we can use template engines without through errors)
  str = buffer.slice(0, len).toString().split("\n");

  return str.slice(0, str.length - 1).join("\n")

}

/*

  function getRegExpMatches

*/

Utils.getRegExpMatches = function(str, re) {

  var match,
      matches = [];

  while (match = re.exec(str))
    matches.push(match[1]);

  return matches;

}

/*

  function watch

*/

Utils.watch = function(sourceDir, sourceExt, destExt, options) {

  if ("*" !== sourceExt) sourceExt = "*." + sourceExt.replace(/^[\*\.]+/g, "");
  if ("*" !== destExt) destExt = (destExt) ? ("*." + destExt.replace(/^[\*\.]+/g, "")) : sourceExt;

  options = options || {};

  chokidar.watch(path.join(sourceDir, "**", sourceExt), options).on("change", function(file) {
    global.server.reload(file);
  });

}

Utils.isProduction = function() {
  return /^prod/i.test(process.env.NODE_ENV);
};
<commit_msg>Utils#isIndexFile: forces "index" to be at beginning, allows case insensitivity<commit_after>
/*

  Utils.js

*/

var fs        = require("fs"),
    url       = require("url"),
    path      = require("path"),
    chokidar  = require("chokidar"),
    Utils;

module.exports = Utils = {};

/*

  function makePathAbsolute

*/

Utils.makePathAbsolute = function(p) {

  if (path.isAbsolute(p))
    return p;
  else
    return path.resolve(process.cwd(), p || "");

}

/*

  function isIndexFile

*/

Utils.isIndexFile = function(file) {
  return /^index[^\/]*$/i.test(file.name);
}

Utils.uniqueExtensions = function(p) {
  return Utils.readDirectory(p).reduce(function(arr, file) {
    if (-1 === arr.indexOf(file.ext)) arr.push(file.ext);
    return arr;
  }, []);
};

/*

  function mapFiles

  Note that we remove leading "." from file extension

*/

Utils.mapFiles = function(p, options) {

  var files, i, indices, results = [];
  options = options || {};

  // Make path absolute before call (for comparison after)
  p = Utils.makePathAbsolute(p);

  files = Utils.readDirectory(p, options.recursive);

  // Sort in reverse order so that directory calls come last. Then move "index" to end.
  if (options.sort) {
    files.sort(function(a, b) { return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0; }).reverse();
    i = files.length;
    while (i-- > 0)
      if (Utils.isIndexFile(files[i]))
        Array.prototype.push.apply(files, files.splice(i, 1));
  }

  // Remove subdirectory files if index.* is encountered
  if (options.bundleFolders) {

    indices = [];

    // Filter out index files (outside of master directory)
    i = files.length;
    while (i-- > 0) {
      if (Utils.isIndexFile(files[i]) && (p !== files[i].dir))
        Array.prototype.push.apply(indices, files.splice(i, 1));
    }

    // Remove indices that are subdirectories of each other
    i = indices.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++) {
        if (i !== j && 0 === indices[i].path.indexOf(indices[j].dir)) {
          indices.splice(i, 1);
          break;
        }
      }

    // Remove files in subdirectories of indices
    i = files.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++)
        if (0 === files[i].path.indexOf(indices[j].dir)) {
          files.splice(i, 1);
          break;
        }

    // Denote indices as bundles
    indices.forEach(function(file) {
      file.bundle = true;
      file.ignored = [
        path.relative(process.cwd(), path.join(file.dir, "*")),
        path.relative(process.cwd(), file.dir + "." + options.ext)
      ];
    });

    // Rejoin indices back into files
    files = files.concat(indices);

  }

  files.forEach(function(file) {
    if (!options.filter || options.filter.indexOf(file.ext) > -1) {
      file.ext = file.ext.replace(/^\./, "");
      file.basePath = p;
      file.folder = path.relative(p, file.path.replace(new RegExp(file.base + "$"), ""));
      results.push(file);
    }
  });

  return results;

}

/*

  function makeRoutes

*/

Utils.makeRoutes = function(route, file, options) {

  var base,
      routes,
      ext,
      options = options || {};

  // !!! WHAT TO DO ABOUT EXTENSIONLESS FILES?
  ext = options.type || file.ext;
  ext = ("undefined" == typeof ext) ? "" : ext.replace(/^\./, "");
  base = (url.resolve((route + "/").replace(/\/\/$/, "/"), file.folder) + "/").replace(/\/\/$/, "/");

  // Wildcard directories
  if ("html" === ext && options.query) {
    // If name starts with @, look for parent directory;
    if ("@" === file.name[0]) base = base.split("/").slice(0, -1).join("/")
    return [base + "/:slug"];
  }

  // Add file and default extension
  routes = [url.resolve(base, file.name + "." + ext)];

  // HTML files are special: not only can they be accessed sans extension, if they are named
  // "index", we allow access via a folder.
  if ("html" === ext) {
    routes.push(url.resolve(base, file.name));
    if (Utils.isIndexFile(file)) routes.push(base);
  }

  return routes;

}

/*

  function readDirectory

*/

Utils.readDirectory = function(p, recursive) {

  var results = [];

  // Set defaults
  if ("undefined" == typeof recursive) recursive = true;
  p = Utils.makePathAbsolute(p);

  // If directory doesn't exist, return nothing
  try {
    fs.lstatSync(p);
  } catch (err) {
    return results;
  }

  // Read in files
  fs.readdirSync(p).forEach(function(file) {

    var stats, parsed;

    // Read file and stats
    file = path.join(p, file);
    stats = fs.lstatSync(file);

    // Recursively walk directory, or add file
    if (stats.isDirectory()) {
      if (recursive)
        results = results.concat(Utils.readDirectory(file, true))
    } else {
      parsed = path.parse(file);
      parsed.path = file;
      results.push(parsed);
    }

  });

  return results;

}

/*

 function readFileHead

 Reads a limited number of characters from a file.

*/

Utils.readFileHead = function(path, chars) {

  var buffer = new Buffer(chars),
      file   = fs.openSync(path, "r"),
      str,
      len;

  // Read in file
  len = fs.readSync(file, buffer, 0, chars, 0);

  // Convert to lines, and discard any fragments
  // (so that we can use template engines without through errors)
  str = buffer.slice(0, len).toString().split("\n");

  return str.slice(0, str.length - 1).join("\n")

}

/*

  function getRegExpMatches

*/

Utils.getRegExpMatches = function(str, re) {

  var match,
      matches = [];

  while (match = re.exec(str))
    matches.push(match[1]);

  return matches;

}

/*

  function watch

*/

Utils.watch = function(sourceDir, sourceExt, destExt, options) {

  if ("*" !== sourceExt) sourceExt = "*." + sourceExt.replace(/^[\*\.]+/g, "");
  if ("*" !== destExt) destExt = (destExt) ? ("*." + destExt.replace(/^[\*\.]+/g, "")) : sourceExt;

  options = options || {};

  chokidar.watch(path.join(sourceDir, "**", sourceExt), options).on("change", function(file) {
    global.server.reload(file);
  });

}

Utils.isProduction = function() {
  return /^prod/i.test(process.env.NODE_ENV);
};
<|endoftext|>


<commit_before>/**
 * Created by kelvinzhang on 7/1/17.
 */

window.onerror = function (msg, url, lineNo, columnNo, error)
{
	let message = [
		'Message: ' + msg,
		'URL: ' + url,
		'Line: ' + lineNo,
		'Column: ' + columnNo,
		'Error object: ' + JSON.stringify(error)
	].join(' - ');

	alert(message);
	return false;
};

let simpleActuation;
let a1Demo;
let a2Demo;
let a3Demo;
let a4Demo;

let measurementDemo;
let sensorDemo;

let motionDemo;
let a1MDemo;
let a2MDemo;
let a3MDemo;
let a4MDemo;

let mclDemo;

const actuationNoiseSliderFormat = {
	min: 0,
	max: 0.5,
	step: 0.01,
	value: 0.01
};

function initMotionDemo()
{
	const path = vanillaPath;
	const x = path[0].x;
	const y = path[0].y;
	const dir = atan2(path[1].y - path[0].y, path[1].x - path[0].x);
	const filter = new ParticleFilter(
		500,
		new OdometryModel(
			getValue('motion_a1') / 100.0,
			getValue('motion_a2') / 100.0,
			getValue('motion_a3') / 100.0,
			getValue('motion_a4') / 100.0),
		undefined,
		new RobotState(x, y, dir),
		0);
	let slider = new Slider("#motion_stride");

	//Individual Simulations
	const s_path = simPath;
	const st_path = straightPath;
	const s_x = s_path[0].x;
	const s_y = s_path[0].y;
	const s_dir = atan2(s_path[1].y - s_path[0].y, s_path[1].x - s_path[0].x);
	const st_x = st_path[0].x;
	const st_y = st_path[0].y;
	const st_dir = atan2(st_path[1].y - st_path[0].y, st_path[1].x - st_path[0].x);
	const exaggerateFilterNoise = Number(document.getElementById("actuation_noise").value);
	const smallParticleCount = 100;
	const filterA1 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			exaggerateFilterNoise,
			0,
			0,
			0
		),
		undefined,
		new RobotState(s_x, s_y, s_dir),
		0);
	const filterA2 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			exaggerateFilterNoise,
			0,
			0
		),
		undefined,
		new RobotState(st_x, st_y, st_dir),
		0);
	const filterA3 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			0,
			exaggerateFilterNoise,
			0
		),
		undefined,
		new RobotState(st_x, st_y, st_dir),
		0);
	const filterA4 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			0,
			0,
			exaggerateFilterNoise
		),
		undefined,
		new RobotState(s_x, s_y, s_dir),
		0);

	slider.on("slide", function (sliderValue)
	{
		motionDemo.setStride(sliderValue);
		a1MDemo.setStride(sliderValue/10000.0);
		a2MDemo.setStride(sliderValue);
		a3MDemo.setStride(sliderValue);
		a4MDemo.setStride(sliderValue/10000.0);
	});

	let a1Slider = new Slider('#motion_a1', actuationNoiseSliderFormat);
	let a2Slider = new Slider('#motion_a2', actuationNoiseSliderFormat);
	let a3Slider = new Slider('#motion_a3', actuationNoiseSliderFormat);
	let a4Slider = new Slider('#motion_a4', actuationNoiseSliderFormat);

	a1Slider.on('slide', (value) => motionDemo.a1 = value);
	a2Slider.on('slide', (value) => motionDemo.a2 = value);
	a3Slider.on('slide', (value) => motionDemo.a3 = value);
	a4Slider.on('slide', (value) => motionDemo.a4 = value);

	let robot = new Robot(filter, path, 0, 0, slider.getValue());
	let robotA1 = new Robot(filterA1, s_path, 0, 0, slider.getValue()/10000.0);
	let robotA2 = new Robot(filterA2, st_path, 0, 0, slider.getValue());
	let robotA3 = new Robot(filterA3, st_path, 0, 0, slider.getValue());
	let robotA4 = new Robot(filterA4, s_path, 0, 0, slider.getValue()/10000.0);
	motionDemo = new RobotDemo('motion_canvas', 'motion_minicanvas', getMap(), robot, 10);
	a1MDemo = new RobotDemo('motion_a1_demo', '', getSimMap(), robotA1, 10);
	a2MDemo = new RobotDemo('motion_a2_demo', '', getSimMap(), robotA2, 10);
	a3MDemo = new RobotDemo('motion_a3_demo', '', getSimMap(), robotA3, 10);
	a4MDemo = new RobotDemo('motion_a4_demo', '', getSimMap(), robotA4, 10);
}

function initMCLDemo()
{
	let slider = new Slider("#mcl_stride", {
		min: 0.01,
		max: 0.2,
		step: 0.01,
		value: 0.04
	});
	slider.on("slide", function (sliderValue)
	{
		mclDemo.setStride(sliderValue);
	});

	let a1Slider = new Slider('#mcl_a1', actuationNoiseSliderFormat);
	let a2Slider = new Slider('#mcl_a2', actuationNoiseSliderFormat);
	let a3Slider = new Slider('#mcl_a3', actuationNoiseSliderFormat);
	let a4Slider = new Slider('#mcl_a4', actuationNoiseSliderFormat);

	a1Slider.on('slide', (value) => mclDemo.a1 = value);
	a2Slider.on('slide', (value) => mclDemo.a2 = value);
	a3Slider.on('slide', (value) => mclDemo.a3 = value);
	a4Slider.on('slide', (value) => mclDemo.a4 = value);

	let sensorRadiusSlider = new Slider('#mcl_sensorRadius', {
		min: 1,
		max: 10,
		step: 0.5
	});
	sensorRadiusSlider.on('slide', (value) => mclDemo.setSensorRadius(value));

	let sensorNoiseSlider = new Slider('#mcl_sensorNoise', {
		min: 0,
		max: 0.3,
		step: 0.01
	});
	sensorNoiseSlider.on('slide', (value) => mclDemo.setSensorNoise(value));

	let colorResSlider = new Slider('#mcl_colorRes', {
		min: 1,
		max: 20,
		step: 1
	});
	colorResSlider.on('slide', (value) => measurementDemo.setColoringResolution(value));

	// let pRatioSlider = new Slider('#mcl_pRatio', {
	// 	min: 0,
	// 	max: 1,
	// 	step: 0.01,
	// 	formatter: function (value)
	// 	{
	// 		return round(value * 100) + "%";
	// 	}
	// });
	// pRatioSlider.on('slide', function (value)
	// {
	// 	mclDemo.robot.filter.resampleRatio = value;
	// });

	const path = vanillaPath;
	const x = path[0].x;
	const y = path[0].y;
	const dir = atan2(path[1].y - path[0].y, path[1].x - path[0].x);
	const filter = new ParticleFilter(
		getValue('mcl_nParticles'),
		new OdometryModel(
			a1Slider.getValue(),
			a2Slider.getValue(),
			a3Slider.getValue(),
			a4Slider.getValue()),
		new BeamModel(
			sensorNoiseSlider.getValue(),
			sensorRadiusSlider.getValue(),
			getMap()),
		new RobotState(x, y, dir),
		1.0);
	robot = new Robot(filter, path, 19, getValue('mcl_sensorRadius'), getValue('mcl_stride'));
	mclDemo = new RobotDemo('mcl_canvas', 'mcl_minicanvas', getMap(), robot, 10);
}

function simulateAllActuations()
{
	a1Demo.simulateActuation();
	a2Demo.simulateActuation();
	a3Demo.simulateActuation();
	a4Demo.simulateActuation();
}

function initActuationDemo()
{
	//Noise parameters
	const a1 = 0.02;
	const a2 = 0.02;
	const a3 = 0.02;
	const a4 = 0.02;

	const firstMove = 2;
	const turn = Math.PI / 6;
	const secondMove = 2;

	simpleActuation = new ActuationDemo('simple_actuation', firstMove, turn, secondMove,
		a1, a2, a3, a4);
	simpleActuation.simulateActuation();

	let noiseSlider = document.getElementById('actuation_noise');
	const noise = Number(noiseSlider.value);
	a1Demo = new ActuationDemo('actuation_a1', firstMove, turn, secondMove,
		noise, 0, 0, 0);
	a2Demo = new ActuationDemo('actuation_a2', firstMove, turn, secondMove,
		0, noise, 0, 0);
	a3Demo = new ActuationDemo('actuation_a3', firstMove, turn, secondMove,
		0, 0, noise, 0);
	a4Demo = new ActuationDemo('actuation_a4', firstMove, turn, secondMove,
		0, 0, 0, noise);
	noiseSlider.addEventListener('input', function(event)
	{
		const sliderValue = Number(event.target.value);
		a1Demo.a1 = sliderValue;
		a2Demo.a2 = sliderValue;
		a3Demo.a3 = sliderValue;
		a4Demo.a4 = sliderValue;

		a1MDemo.a1 = sliderValue;
		a2MDemo.a2 = sliderValue;
		a3MDemo.a3 = sliderValue;
		a4MDemo.a4 = sliderValue;
	});
	noiseSlider.addEventListener('change', simulateAllActuations);
	simulateAllActuations();
}

function initMeasurementDemo()
{
	let map = getMap();
	// compactMap(map);
	let nLasersSlider = new Slider('#nLasers', {
		min: 6,
		max: 36,
		step: 1
	});
	nLasersSlider.on('slide', (value) => measurementDemo.setNLasers(value));
	nLasersSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let sensorRadiusSlider = new Slider('#sensorRadius', {
		min: 1,
		max: 10,
		step: 0.5
	});
	sensorRadiusSlider.on('slide', (value) => measurementDemo.setSensorRadius(value));
	sensorRadiusSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let sensorNoiseSlider = new Slider('#sensorNoise', {
		min: 0,
		max: 0.5,
		step: 0.02
	});
	sensorNoiseSlider.on('slide', (value) => measurementDemo.setSensorNoise(value));
	sensorNoiseSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let colorResSlider = new Slider('#colorRes', {
		min: 1,
		max: 20,
		step: 1
	});
	colorResSlider.on('slide', function (value)
	{
		measurementDemo.setColoringResolution(value);
	});
	colorResSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	measurementDemo = new BeamModelDemo('sensor_model_demo', map,
		sensorRadiusSlider.getValue(), sensorNoiseSlider.getValue(), 'sensor_model_mini');
}

function onFirstAppear(selector, callback)
{
	$(selector).appear().on('appear', function (event, $targets)
	{
		callback(event, $targets);
		$(selector).off('appear');
	});
}

function initSensorDemo(id)
{
	let noiseSlider = new Slider("#sensor_demo_sensorNoise", {
		min: 0,
		max: 4,
		step: 0.2,
		value: 2
	});
	sensorDemo = new SensorDemo(id, noiseSlider.getValue());
	noiseSlider.on("slideStop", (sliderValue) => sensorDemo.setSensorNoise(sliderValue));
	let repSlider = new Slider('#nSamples', {
		min: 0,
		max: 5,
		step: 0.2,
		value: 2,
		formatter: (value) => {return round(Math.pow(10, value));}
	});
}

(function($){
  $(function(){

    $('.button-collapse').sideNav();
    $('.parallax').parallax();

  }); // end of document ready
})(jQuery); // end of jQuery name space

function init()
{
	smoothenPath(vanillaPath);
	// onFirstAppear('#simple_actuation', function (e, $t)
	// {
		initActuationDemo();
	// });
	// onFirstAppear('#motion_a1_demo', function (e, $t)
	// {
		initMotionDemo();
	// });
	// onFirstAppear('#mcl_canvas', function (e, $t)
	// {
		initMCLDemo();
	// });
	// onFirstAppear('#sensor_model_demo', function (e, $t)
	// {
		initMeasurementDemo();
	// });
	onFirstAppear('#sensor_demo', (e) => initSensorDemo(e.target.id));
}
<commit_msg>use lambda expressions<commit_after>/**
 * Created by kelvinzhang on 7/1/17.
 */

window.onerror = function (msg, url, lineNo, columnNo, error)
{
	let message = [
		'Message: ' + msg,
		'URL: ' + url,
		'Line: ' + lineNo,
		'Column: ' + columnNo,
		'Error object: ' + JSON.stringify(error)
	].join(' - ');

	alert(message);
	return false;
};

let simpleActuation;
let a1Demo;
let a2Demo;
let a3Demo;
let a4Demo;

let measurementDemo;
let sensorDemo;

let motionDemo;
let a1MDemo;
let a2MDemo;
let a3MDemo;
let a4MDemo;

let mclDemo;

const actuationNoiseSliderFormat = {
	min: 0,
	max: 0.5,
	step: 0.01,
	value: 0.01
};

function initMotionDemo()
{
	const path = vanillaPath;
	const x = path[0].x;
	const y = path[0].y;
	const dir = atan2(path[1].y - path[0].y, path[1].x - path[0].x);
	const filter = new ParticleFilter(
		500,
		new OdometryModel(
			getValue('motion_a1') / 100.0,
			getValue('motion_a2') / 100.0,
			getValue('motion_a3') / 100.0,
			getValue('motion_a4') / 100.0),
		undefined,
		new RobotState(x, y, dir),
		0);
	let slider = new Slider("#motion_stride");

	//Individual Simulations
	const s_path = simPath;
	const st_path = straightPath;
	const s_x = s_path[0].x;
	const s_y = s_path[0].y;
	const s_dir = atan2(s_path[1].y - s_path[0].y, s_path[1].x - s_path[0].x);
	const st_x = st_path[0].x;
	const st_y = st_path[0].y;
	const st_dir = atan2(st_path[1].y - st_path[0].y, st_path[1].x - st_path[0].x);
	const exaggerateFilterNoise = Number(document.getElementById("actuation_noise").value);
	const smallParticleCount = 100;
	const filterA1 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			exaggerateFilterNoise,
			0,
			0,
			0
		),
		undefined,
		new RobotState(s_x, s_y, s_dir),
		0);
	const filterA2 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			exaggerateFilterNoise,
			0,
			0
		),
		undefined,
		new RobotState(st_x, st_y, st_dir),
		0);
	const filterA3 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			0,
			exaggerateFilterNoise,
			0
		),
		undefined,
		new RobotState(st_x, st_y, st_dir),
		0);
	const filterA4 = new ParticleFilter(
		smallParticleCount,
		new OdometryModel(
			0,
			0,
			0,
			exaggerateFilterNoise
		),
		undefined,
		new RobotState(s_x, s_y, s_dir),
		0);

	slider.on("slide", function (sliderValue)
	{
		motionDemo.setStride(sliderValue);
		a1MDemo.setStride(sliderValue/10000.0);
		a2MDemo.setStride(sliderValue);
		a3MDemo.setStride(sliderValue);
		a4MDemo.setStride(sliderValue/10000.0);
	});

	let a1Slider = new Slider('#motion_a1', actuationNoiseSliderFormat);
	let a2Slider = new Slider('#motion_a2', actuationNoiseSliderFormat);
	let a3Slider = new Slider('#motion_a3', actuationNoiseSliderFormat);
	let a4Slider = new Slider('#motion_a4', actuationNoiseSliderFormat);

	a1Slider.on('slide', (value) => motionDemo.a1 = value);
	a2Slider.on('slide', (value) => motionDemo.a2 = value);
	a3Slider.on('slide', (value) => motionDemo.a3 = value);
	a4Slider.on('slide', (value) => motionDemo.a4 = value);

	let robot = new Robot(filter, path, 0, 0, slider.getValue());
	let robotA1 = new Robot(filterA1, s_path, 0, 0, slider.getValue()/10000.0);
	let robotA2 = new Robot(filterA2, st_path, 0, 0, slider.getValue());
	let robotA3 = new Robot(filterA3, st_path, 0, 0, slider.getValue());
	let robotA4 = new Robot(filterA4, s_path, 0, 0, slider.getValue()/10000.0);
	motionDemo = new RobotDemo('motion_canvas', 'motion_minicanvas', getMap(), robot, 10);
	a1MDemo = new RobotDemo('motion_a1_demo', '', getSimMap(), robotA1, 10);
	a2MDemo = new RobotDemo('motion_a2_demo', '', getSimMap(), robotA2, 10);
	a3MDemo = new RobotDemo('motion_a3_demo', '', getSimMap(), robotA3, 10);
	a4MDemo = new RobotDemo('motion_a4_demo', '', getSimMap(), robotA4, 10);
}

function initMCLDemo()
{
	let slider = new Slider("#mcl_stride", {
		min: 0.01,
		max: 0.2,
		step: 0.01,
		value: 0.04
	});
	slider.on("slide", (sliderValue) => mclDemo.setStride(sliderValue));

	let a1Slider = new Slider('#mcl_a1', actuationNoiseSliderFormat);
	let a2Slider = new Slider('#mcl_a2', actuationNoiseSliderFormat);
	let a3Slider = new Slider('#mcl_a3', actuationNoiseSliderFormat);
	let a4Slider = new Slider('#mcl_a4', actuationNoiseSliderFormat);

	a1Slider.on('slide', (value) => mclDemo.a1 = value);
	a2Slider.on('slide', (value) => mclDemo.a2 = value);
	a3Slider.on('slide', (value) => mclDemo.a3 = value);
	a4Slider.on('slide', (value) => mclDemo.a4 = value);

	let sensorRadiusSlider = new Slider('#mcl_sensorRadius', {
		min: 1,
		max: 10,
		step: 0.5
	});
	sensorRadiusSlider.on('slide', (value) => mclDemo.setSensorRadius(value));

	let sensorNoiseSlider = new Slider('#mcl_sensorNoise', {
		min: 0,
		max: 0.3,
		step: 0.01
	});
	sensorNoiseSlider.on('slide', (value) => mclDemo.setSensorNoise(value));

	let colorResSlider = new Slider('#mcl_colorRes', {
		min: 1,
		max: 20,
		step: 1
	});
	colorResSlider.on('slide', (value) => measurementDemo.setColoringResolution(value));

	// let pRatioSlider = new Slider('#mcl_pRatio', {
	// 	min: 0,
	// 	max: 1,
	// 	step: 0.01,
	// 	formatter: function (value)
	// 	{
	// 		return round(value * 100) + "%";
	// 	}
	// });
	// pRatioSlider.on('slide', function (value)
	// {
	// 	mclDemo.robot.filter.resampleRatio = value;
	// });

	const path = vanillaPath;
	const x = path[0].x;
	const y = path[0].y;
	const dir = atan2(path[1].y - path[0].y, path[1].x - path[0].x);
	const filter = new ParticleFilter(
		getValue('mcl_nParticles'),
		new OdometryModel(
			a1Slider.getValue(),
			a2Slider.getValue(),
			a3Slider.getValue(),
			a4Slider.getValue()),
		new BeamModel(
			sensorNoiseSlider.getValue(),
			sensorRadiusSlider.getValue(),
			getMap()),
		new RobotState(x, y, dir),
		1.0);
	robot = new Robot(filter, path, 19, getValue('mcl_sensorRadius'), getValue('mcl_stride'));
	mclDemo = new RobotDemo('mcl_canvas', 'mcl_minicanvas', getMap(), robot, 10);
}

function simulateAllActuations()
{
	a1Demo.simulateActuation();
	a2Demo.simulateActuation();
	a3Demo.simulateActuation();
	a4Demo.simulateActuation();
}

function initActuationDemo()
{
	//Noise parameters
	const a1 = 0.02;
	const a2 = 0.02;
	const a3 = 0.02;
	const a4 = 0.02;

	const firstMove = 2;
	const turn = Math.PI / 6;
	const secondMove = 2;

	simpleActuation = new ActuationDemo('simple_actuation', firstMove, turn, secondMove,
		a1, a2, a3, a4);
	simpleActuation.simulateActuation();

	let noiseSlider = document.getElementById('actuation_noise');
	const noise = Number(noiseSlider.value);
	a1Demo = new ActuationDemo('actuation_a1', firstMove, turn, secondMove,
		noise, 0, 0, 0);
	a2Demo = new ActuationDemo('actuation_a2', firstMove, turn, secondMove,
		0, noise, 0, 0);
	a3Demo = new ActuationDemo('actuation_a3', firstMove, turn, secondMove,
		0, 0, noise, 0);
	a4Demo = new ActuationDemo('actuation_a4', firstMove, turn, secondMove,
		0, 0, 0, noise);
	noiseSlider.addEventListener('input', function(event)
	{
		const sliderValue = Number(event.target.value);
		a1Demo.a1 = sliderValue;
		a2Demo.a2 = sliderValue;
		a3Demo.a3 = sliderValue;
		a4Demo.a4 = sliderValue;

		a1MDemo.a1 = sliderValue;
		a2MDemo.a2 = sliderValue;
		a3MDemo.a3 = sliderValue;
		a4MDemo.a4 = sliderValue;
	});
	noiseSlider.addEventListener('change', simulateAllActuations);
	simulateAllActuations();
}

function initMeasurementDemo()
{
	let map = getMap();
	// compactMap(map);
	let nLasersSlider = new Slider('#nLasers', {
		min: 6,
		max: 36,
		step: 1
	});
	nLasersSlider.on('slide', (value) => measurementDemo.setNLasers(value));
	nLasersSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let sensorRadiusSlider = new Slider('#sensorRadius', {
		min: 1,
		max: 10,
		step: 0.5
	});
	sensorRadiusSlider.on('slide', (value) => measurementDemo.setSensorRadius(value));
	sensorRadiusSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let sensorNoiseSlider = new Slider('#sensorNoise', {
		min: 0,
		max: 0.5,
		step: 0.02
	});
	sensorNoiseSlider.on('slide', (value) => measurementDemo.setSensorNoise(value));
	sensorNoiseSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	let colorResSlider = new Slider('#colorRes', {
		min: 1,
		max: 20,
		step: 1
	});
	colorResSlider.on('slide', (value) => measurementDemo.setColoringResolution(value));
	colorResSlider.on('slideStop', () => measurementDemo.colorMapIfShould());

	measurementDemo = new BeamModelDemo('sensor_model_demo', map,
		sensorRadiusSlider.getValue(), sensorNoiseSlider.getValue(), 'sensor_model_mini');
}

function onFirstAppear(selector, callback)
{
	$(selector).appear().on('appear', function (event, $targets)
	{
		callback(event, $targets);
		$(selector).off('appear');
	});
}

function initSensorDemo(id)
{
	let noiseSlider = new Slider("#sensor_demo_sensorNoise", {
		min: 0,
		max: 4,
		step: 0.2,
		value: 2
	});
	sensorDemo = new SensorDemo(id, noiseSlider.getValue());
	noiseSlider.on("slideStop", (sliderValue) => sensorDemo.setSensorNoise(sliderValue));
	let repSlider = new Slider('#nSamples', {
		min: 0,
		max: 5,
		step: 0.2,
		value: 2,
		formatter: (value) => {return round(Math.pow(10, value));}
	});
}

(function($){
  $(function(){

    $('.button-collapse').sideNav();
    $('.parallax').parallax();

  }); // end of document ready
})(jQuery); // end of jQuery name space

function init()
{
	smoothenPath(vanillaPath);
	// onFirstAppear('#simple_actuation', function (e, $t)
	// {
		initActuationDemo();
	// });
	// onFirstAppear('#motion_a1_demo', function (e, $t)
	// {
		initMotionDemo();
	// });
	// onFirstAppear('#mcl_canvas', function (e, $t)
	// {
		initMCLDemo();
	// });
	// onFirstAppear('#sensor_model_demo', function (e, $t)
	// {
		initMeasurementDemo();
	// });
	onFirstAppear('#sensor_demo', (e) => initSensorDemo(e.target.id));
}
<|endoftext|>


<commit_before>/*
 * jqPivot, an advanced grid plugin for jQuery.
 * (c) Rob Larsen, 2012
 * Stay tuned.
 * Plugin boilerplate for now.
 */
;(function ( $, window, document, undefined ) {

    $.fn.jqPivot = function ( options ) {

        options = $.extend( {}, $.fn.jqPivot.options, options );

        return this.each(function () {

            var elem = $(this);

        });
    };

    $.fn.jqPivot.options = {

        key: "value",
        myMethod: function ( elem, param ) {

        }
    };

})( jQuery, window, document );<commit_msg>First Alpha<commit_after><|endoftext|>


<commit_before>var bower = require('bower');
var fsx = require('fs-extra');
var async = require('async');

/**
 * Update client-side dependencies
 */

async.auto({

  'sails.io.js': function(cb) {
    bower.commands
      .install(['sails.io.js'], {
        save: false
      }, { /* custom config */ })
      .on('end', function(installed) {
        fsx.copy(
          'bower_components/sails.io.js/dist/sails.io.js',
          'templates/assets/js/dependencies/sails.io.js',
          cb);
      });
  },

  // ... future front-end dependencies here ...

},
function done(err, async_data) {
  if (err) return console.error(err);

  // Delete bower_components
  fsx.removeSync('bower_components');

  console.log('Done.');
});
<commit_msg>Remove unused build dir<commit_after><|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var utils = require('lazy-cache')(require);
var fn = require;

/**
 * Lazily required module dependencies
 */

require = utils;
require('write-json');
require('resolve-dir');
require('rimraf', 'del');
require = fn;

/**
 * Read a JSON file.
 *
 * @param {String} `fp`
 * @return {Object}
 */

utils.readJson = function(fp) {
  try {
    var str = fs.readFileSync(path.resolve(fp), 'utf8');
    return JSON.parse(str);
  } catch(err) {}
  return {};
};

/**
 * Expose `utils`
 */

module.exports = utils;
<commit_msg>organize utils<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var utils = require('lazy-cache')(require);
var fn = require;

/**
 * Lazily required module dependencies
 */

require = utils;
require('extend-shallow', 'extend');
require('unset-value', 'unset');
require('set-value', 'set');
require('get-value', 'get');
require('has-value', 'has');
require('rimraf', 'del');
require('resolve-dir');
require('write-json');
require = fn;

/**
 * Create the key to use for getting and setting values.
 * If the key contains a filepath, and the filepath has
 * dots in it, we need to escape them to ensure that
 * `set-value` doesn't split on those dots.
 */

utils.toKey = function(fp, key) {
  if (typeof fp !== 'string') {
    throw new TypeError('expected fp to be a string');
  }
  fp = fp.split('.').join('\\.');
  return fp + (key ? ('.' + key) : '');
};

/**
 * Read a JSON file.
 *
 * @param {String} `fp`
 * @return {Object}
 */

utils.readJson = function(fp) {
  try {
    var str = fs.readFileSync(path.resolve(fp), 'utf8');
    return JSON.parse(str);
  } catch(err) {}
  return {};
};

/**
 * Expose `utils`
 */

module.exports = utils;
<|endoftext|>


<commit_before>/*
    Cycles Render Time Calculator (CRTC)
    Calculate how long your Blender Cycles Engine renders will take.

    Created 2013 Triangle717 & rioforce
    <http://Triangle717.WordPress.com/>
    <http://rioforce.wordpress.com/>

-------------------------------------
Cycles Render Time Calculator - Web Version
*/

function changeFields() {
    /* Change field lables depending on values chosen */

    // Get state of Progressive Refine radio button
    var rendertype = document.getElementById("render").checked

    // User is rendering using Tiles
    if (!rendertype) {
        document.getElementById("numof1label").innerHTML="Number of Tiles: ";
        document.getElementById("numof2label").innerHTML="Render time of one Tile (in seconds) ";
        }

    // User is rendering using Progressive Refine
    else {
        document.getElementById("numof1label").innerHTML="Number of Samples: ";
        document.getElementById("numof2label").innerHTML="Render time of one Sample (in seconds) ";
        }
};

function isVideo() {
    /* Change field lables depending on if video is being rendered */

    // Get state of check box
    var value = document.getElementById("videocheck").checked

    // Display the field for number of frames
    if (value) {
        document.getElementById("numofframes").innerHTML='Number of frames in animation:
\n<input type="text" placeholder="250" autocomplete="off">
';
        }

    // It is unchecked, display nothing
    else {
        document.getElementById("numofframes").innerHTML="";
        }
};

function tileVideoRender(paramseconds) {
    /* Calculates Animation Render Time (Using Tiles) */

    tileframenumber = prompt("\nHow many frames are in your animation? ");

    // Convert input to integers using Base10
    tileframenumber = parseInt(tileframenumber, 10);

    // More mathamatical functions
    seconds = paramseconds * tileframenumber;
    minutes = seconds / 60;
    hours = seconds / 3600;

    // It will take over an hour
    if (seconds >= 3600.0) {
        console.log("It will take approximately " + Math.round(hours) +  "hours to render your animation.");
        }

    // It will take over a minute but less than an hour
    else if (seconds >= 60.0 && seconds < 3599.9) {
        console.log("It will take approximately " + Math.round(minutes) + " minutes to render your animation.");
        }

    // It will take only seconds
    else {
        console.log("It will take approximately " + Math.round(seconds) + " seconds to render your animation.");
        }
};

function doMath(number1, number2) {
    /* Perform the math problems */

    // Holds our math results
    values = [];

    // Convert input to integers using Base10
    number1 = parseInt(number1, 10);
    number2 = parseInt(number2, 10);

    // Calculate the seconds, minutes, and hours
    var seconds = number1 * number2;
    var minutes = seconds / 60;
    var hours = seconds / 3600;

    // Round the calculations off
    seconds = Math.round(seconds);
    minutes = Math.round(minutes);
    hours = Math.round(hours);

    // Add the results to the the array and return it
    values.push(seconds);
    values.push(minutes);
    values.push(hours);
    return values;
};

function calculate() {
    /*  Calculate the render times! */

    // Get the numbers from the fields
    // TODO: Add check to make sure they are numbers
    var first_number = document.getElementById("field1").value;
    var second_number = document.getElementById("field2").value;
    //var isvideo = document.getElementById("videocheck").checked;

    // Do the math
    var results = doMath(first_number, second_number);

    // Standard messages that may be edited later
    var hr_text = " hours"
    var min_text = " minutes"
    var sec_text = " seconds"

    // It will take over an hour
    if (results[0] >= 3600.0) {

        // If it is exactly one hour, change the message to remove the 's'
        if (results[0] === 3600) {
            hr_text = " hour";
        }
        document.getElementById("results").innerHTML="" + results[2] + hr_text + "";
        }

    // It will take over a minute but less than an hour
    else if (results[0] >= 60 && results[0] < 3599.9) {

        // If it is exactly one minute, change the message to remove the 's'
        if (results[0] === 60) {
            min_text = " minute";
        }
        document.getElementById("results").innerHTML="" + results[1] + min_text + "";
        }

    // It will take only seconds
    else {

        // If it is exactly one second, change the message to remove the 's'
        if (results[0] === 1) {
            sec_text = " second";
        }
        document.getElementById("results").innerHTML="" + results[0] + sec_text + "";
        }

    // Do something else here!
    //document.getElementById("results").innerHTML="10 hours";

};
<commit_msg>Part of video render code added<commit_after>/*
    Cycles Render Time Calculator (CRTC)
    Calculate how long your Blender Cycles Engine renders will take.

    Created 2013 Triangle717 & rioforce
    <http://Triangle717.WordPress.com/>
    <http://rioforce.wordpress.com/>

-------------------------------------
Cycles Render Time Calculator - Web Version
*/

function changeFields() {
    /* Change field lables depending on values chosen */

    // Get state of Progressive Refine radio button
    var rendertype = document.getElementById("render").checked

    // User is rendering using Tiles
    if (!rendertype) {
        document.getElementById("numof1label").innerHTML="Number of Tiles: ";
        document.getElementById("numof2label").innerHTML="Render time of one Tile (in seconds) ";
        }

    // User is rendering using Progressive Refine
    else {
        document.getElementById("numof1label").innerHTML="Number of Samples: ";
        document.getElementById("numof2label").innerHTML="Render time of one Sample (in seconds) ";
        }
};

function isVideo() {
    /* Change field lables depending on if video is being rendered */

    // Get state of check box
    var value = document.getElementById("videocheck").checked

    // Display the field for number of frames
    if (value) {
        document.getElementById("numofframes").innerHTML='Number of frames in animation:
\n<input id="field3" type="text" placeholder="250" autocomplete="off">
';
        }

    // It is unchecked, display nothing
    else {
        document.getElementById("numofframes").innerHTML="";
        }
};

function tileVideoRender(paramseconds) {
    /* Calculates Animation Render Time (Using Tiles) */

    tileframenumber = prompt("\nHow many frames are in your animation? ");

    // Convert input to integers using Base10
    tileframenumber = parseInt(tileframenumber, 10);

    // More mathamatical functions
    seconds = paramseconds * tileframenumber;
    minutes = seconds / 60;
    hours = seconds / 3600;

    // It will take over an hour
    if (seconds >= 3600.0) {
        console.log("It will take approximately " + Math.round(hours) +  "hours to render your animation.");
        }

    // It will take over a minute but less than an hour
    else if (seconds >= 60.0 && seconds < 3599.9) {
        console.log("It will take approximately " + Math.round(minutes) + " minutes to render your animation.");
        }

    // It will take only seconds
    else {
        console.log("It will take approximately " + Math.round(seconds) + " seconds to render your animation.");
        }
};

function doMath(number1, number2) {
    /* Perform the math problems */

    // Holds our math results
    values = [];

    // Convert input to integers using Base10
    number1 = parseInt(number1, 10);
    number2 = parseInt(number2, 10);

    // Calculate the seconds, minutes, and hours
    var seconds = number1 * number2;
    var minutes = seconds / 60;
    var hours = seconds / 3600;

    // Round the calculations off
    seconds = Math.round(seconds);
    minutes = Math.round(minutes);
    hours = Math.round(hours);

    // Add the results to the the array and return it
    values.push(seconds);
    values.push(minutes);
    values.push(hours);

    // Check if a video is being rendered
    var isvideo = document.getElementById("videocheck").checked;

    if (isvideo) {
        var number_of_frames = document.getElementById("field3").value;
        console.log(number_of_frames);
        }

    return values;
};

function calculate() {
    /*  Calculate the render times! */

    // Get the numbers from the fields
    // TODO: Add check to make sure they are numbers
    var first_number = document.getElementById("field1").value;
    var second_number = document.getElementById("field2").value;

    // Do the math
    var results = doMath(first_number, second_number);

    // Standard messages that may be edited later
    var hr_text = " hours"
    var min_text = " minutes"
    var sec_text = " seconds"

    // It will take over an hour
    if (results[0] >= 3600.0) {

        // If it is exactly one hour, change the message to remove the 's'
        if (results[0] === 3600) {
            hr_text = " hour";
        }
        document.getElementById("results").innerHTML="" + results[2] + hr_text + "";
        }

    // It will take over a minute but less than an hour
    else if (results[0] >= 60 && results[0] < 3599.9) {

        // If it is exactly one minute, change the message to remove the 's'
        if (results[0] === 60) {
            min_text = " minute";
        }
        document.getElementById("results").innerHTML="" + results[1] + min_text + "";
        }

    // It will take only seconds
    else {

        // If it is exactly one second, change the message to remove the 's'
        if (results[0] === 1) {
            sec_text = " second";
        }
        document.getElementById("results").innerHTML="" + results[0] + sec_text + "";
        }

    // Do something else here!
    //document.getElementById("results").innerHTML="10 hours";

};
<|endoftext|>


<commit_before>var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var marked = require('marked');
var ghpages = require('gh-pages');
var loading =  require('loading-cli');
var mkdirp = require('mkdirp');
var renderer = new marked.Renderer();
var color = require('colors-cli/safe')
var error = color.red.bold;
var warn = color.yellow;
var notice = color.blue;
var success = color.green;

// console.log(error('Error!'));
// console.log(warn('Warning'));
// console.log(notice('Notice'));

renderer.heading = function (text, level) {
    if(/[\u4E00-\u9FA5]/i.test(text)){
        return '<h' + level + ' id="'+text+'">'+text+'</h' + level + '>';
    }else{
        var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
        return '<h' + level + ' id="'+escapedText+'">'+text+'</h' + level + '>';
    }
}

marked.setOptions({
  renderer: renderer,
  // gfm: true,
  // tables: true,
  // breaks: false,
  // pedantic: false,
  // sanitize: true,
  // smartLists: true,
  // smartypants: false
  // highlight: function (code, lang, callback) {
  //   console.log("tes")
  //   require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {
  //     callback(err, result.toString());
  //   });
  // }
});

// 删除文件夹
exec('rm -rf .deploy');

MarkedToHTMLSave('.deploy/index.html','README.md'.toString(),function(err){
    if (err) return console.log(error(err));
    console.log(notice('  → '+"ok!"));

    MarkedToHTMLSave('.deploy/index.en.html','README-en.md'.toString(),function(err){
        if (err) return console.log(error(err));
        console.log(notice('  → '+"ok!"));
        var load = loading('  Pushing code!!')
        load.start()
        ghpages.publish(path.join(__dirname, '.deploy'),{
            repo: 'https://github.com/jaywcjlove/awesome-mac.git',
            branch: 'gh-pages'
        }, function(err) {
            if(err) return console.log(error('  → '+"ok!"+err));
            load.stop()
            console.log(success('\n\n   '+"Push success!!"));
            // 删除文件夹
            exec('rm -rf .deploy');
        });

    })

})

function MarkedToHTMLSave(_path,form_file,callback){
    var README_str = fs.readFileSync(form_file);
    var dirname = path.dirname(_path)
    var basename = path.basename(_path)
    var md_basename = path.basename(form_file)
    // console.log("md_basename::",md_basename)
    console.log('\n  ☆ '+_path+'\n');
    mkdirp(dirname, function (err) {
        if (err) return callback(err);
        console.log(notice('  → '+dirname+"文件夹创建成功!"));
        marked(README_str.toString(),function(err,html){
            if (err) return callback(err);
            console.log(notice('  → ['+form_file+"]成功转换成HTML!"));
            html = MDhrefToPath(html);
            fs.writeFile(_path,htmlAndStyle(html),function(err){
                if (err) return callback(err);
                callback(err)
            })
        })
    });
}

function MDhrefToPath(html){
    var reg = new RegExp(']*href="([^"]*\.md)"[^>]*>','ig')
    return html.replace(reg,function(a,st){
        // console.log(a,st)
        var a

        if(st.indexOf('README.md')>-1){
            a = a.replace(st,'index.html')
        }
        if(st.indexOf('README-en.md')>-1){
            a = a.replace(st,'index.en.html')
        }
        return a
    })

}

function htmlAndStyle(html){
    var str = ''
    str += '<!DOCTYPE html>\n'
    str += '\n'
    str += '\n'
    str += '    <meta charset="UTF-8">\n'
    str += '    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">\n'
    str += '    <title>Awesome Mac</title>\n'
    str += '    '
    str += '\n'
    str += '\n
'
    str += html
    str += '
\n\n'
    str += '\n'
    return str;
}<commit_msg>Modify the generated HTML content.<commit_after>var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var marked = require('marked');
var ghpages = require('gh-pages');
var loading =  require('loading-cli');
var mkdirp = require('mkdirp');
var renderer = new marked.Renderer();
var color = require('colors-cli/safe')
var error = color.red.bold;
var warn = color.yellow;
var notice = color.blue;
var success = color.green;

// console.log(error('Error!'));
// console.log(warn('Warning'));
// console.log(notice('Notice'));

renderer.heading = function (text, level) {
    if(/[\u4E00-\u9FA5]/i.test(text)){
        return '<h' + level + ' id="'+text+'">'+text+'</h' + level + '>';
    }else{
        var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
        return '<h' + level + ' id="'+escapedText+'">'+text+'</h' + level + '>';
    }
}

marked.setOptions({
  renderer: renderer,
  // gfm: true,
  // tables: true,
  // breaks: false,
  // pedantic: false,
  // sanitize: true,
  // smartLists: true,
  // smartypants: false
  // highlight: function (code, lang, callback) {
  //   console.log("tes")
  //   require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {
  //     callback(err, result.toString());
  //   });
  // }
});

// 删除文件夹
exec('rm -rf .deploy');

MarkedToHTMLSave('.deploy/index.html','README.md'.toString(),function(err){
    if (err) return console.log(error(err));
    console.log(notice('  → '+"ok!"));

    MarkedToHTMLSave('.deploy/index.en.html','README-en.md'.toString(),function(err){
        if (err) return console.log(error(err));
        console.log(notice('  → '+"ok!"));
        var load = loading('  Pushing code!!')
        load.start()
        ghpages.publish(path.join(__dirname, '.deploy'),{
            repo: 'https://github.com/jaywcjlove/awesome-mac.git',
            branch: 'gh-pages'
        }, function(err) {
            if(err) return console.log(error('  → '+"ok!"+err));
            load.stop()
            console.log(success('\n\n   '+"Push success!!"));
            // 删除文件夹
            exec('rm -rf .deploy');
        });

    })

})

function MarkedToHTMLSave(_path,form_file,callback){
    var README_str = fs.readFileSync(form_file);
    var dirname = path.dirname(_path)
    var basename = path.basename(_path)
    var md_basename = path.basename(form_file)
    // console.log("md_basename::",md_basename)
    console.log('\n  ☆ '+_path+'\n');
    mkdirp(dirname, function (err) {
        if (err) return callback(err);
        console.log(notice('  → '+dirname+"文件夹创建成功!"));
        marked(README_str.toString(),function(err,html){
            if (err) return callback(err);
            console.log(notice('  → ['+form_file+"]成功转换成HTML!"));
            html = MDhrefToPath(html);
            fs.writeFile(_path,htmlAndStyle(html),function(err){
                if (err) return callback(err);
                callback(err)
            })
        })
    });
}

function MDhrefToPath(html){
    var reg = new RegExp(']*href="([^"]*\.md)"[^>]*>','ig')
    return html.replace(reg,function(a,st){
        // console.log(a,st)
        var a

        if(st.indexOf('README.md')>-1){
            a = a.replace(st,'index.html')
        }
        if(st.indexOf('README-en.md')>-1){
            a = a.replace(st,'index.en.html')
        }
        return a
    })

}

function htmlAndStyle(html){
    var str = ''
    str += '<!DOCTYPE html>\n'
    str += '\n'
    str += '\n'
    str += '    <meta charset="UTF-8">\n'
    str += '    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">\n'
    str += '    <title>Awesome Mac</title>\n'
    str += '    '
    str += '\n'
    str += '\n'
    str += ' <svg viewBox="0 0 250 250"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg> '
    str += '
'
    str += html
    str += '
\n\n'
    str += '\n'
    return str;
}<|endoftext|>


<commit_before>
/*

  Utils.js

*/

var __rootDir = process.cwd(),
    fs        = require("fs"),
    url       = require("url"),
    path      = require("path"),
    Utils;

module.exports = Utils = {};

/*

  function getRootPath

*/

Utils.getRootPath = function() {
  return __rootDir;
}

/*

  function makePathAbsolute

*/

Utils.makePathAbsolute = function(p) {

  return path.resolve(Utils.getRootPath(), p || "");

}

/*

  function isIndexFile

*/

Utils.isIndexFile = function(file) {
  return /index[^\/]*$/.test(file.name);
}

/*

  function mapFiles

*/

Utils.mapFiles = function(p, options) {

  var files, i, indices, results = [];
  options = options || {};

  // Make path absolute before call (for comparison after)
  p = Utils.makePathAbsolute(p);

  files = Utils.readDirectory(p, options.recursive);

  // Sort in reverse order so that directory calls come last. Then move "index" to end.
  if (options.sort) {
    files.sort(function(a, b) { return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0; }).reverse();
    i = files.length;
    while (i-- > 0)
      if (Utils.isIndexFile(files[i]))
        Array.prototype.push.apply(files, files.splice(i, 1));
  }

  // Remove subdirectory files if index.* is encountered
  if (options.bundleFolders) {

    indices = [];

    // Filter out index files (outside of master directory)
    i = files.length;
    while (i-- > 0) {
      if (Utils.isIndexFile(files[i]) && (p !== files[i].dir))
        Array.prototype.push.apply(indices, files.splice(i, 1));
    }

    // Remove indices that are subdirectories of each other
    i = indices.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++) {
        if (i !== j && 0 === indices[i].path.indexOf(indices[j].dir)) {
          indices.splice(i, 1);
          break;
        }
      }

    // Remove files in subdirectories of indices
    i = files.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++)
        if (0 === files[i].path.indexOf(indices[j].dir)) {
          files.splice(i, 1);
          break;
        }

    // Denote indices as bundles
    indices.forEach(function(file) { file.bundle = true });

    // Rejoin indices back into files
    files = files.concat(indices);

  }

  files.forEach(function(file) {
    file.folder = path.relative(p, file.path.replace(new RegExp(file.base + "$"), ""));
    if (!options.filter || options.filter.indexOf(file.ext) > -1) results.push(file);
  });

  return results;

}

/*

  function makeRoutes

*/

Utils.makeRoutes = function(route, file, options) {

  var base,
      routes,
      ext,
      options = options || {};

  // !!! WHAT TO DO ABOUT EXTENSIONLESS FILES?
  ext = options.type || file.ext;
  ext = ("undefined" == typeof ext) ? "" : ext.replace(/^\./, "");
  base = (url.resolve((route + "/").replace(/\/\/$/, "/"), file.folder) + "/").replace(/\/\/$/, "/");

  // Wildcard directories
  if ("html" === ext && options.query) {
    // If name starts with @, look for parent directory;
    if ("@" === file.name[0]) base = base.split("/").slice(0, -1).join("/")
    return [base + "/:slug"];
  }

  // Add file and default extension
  routes = [url.resolve(base, file.name + "." + ext)];

  // If the file is named "index", we allow it to function as the folder.
  if ("html" === ext && Utils.isIndexFile(file)) routes.push(base);

  return routes;

}

/*

  function readDirectory

*/

Utils.readDirectory = function(p, recursive) {

  var results = [];

  // Set defaults
  if ("undefined" == typeof recursive) recursive = true;
  p = Utils.makePathAbsolute(p);

  // If directory doesn't exist, return nothing
  try {
    fs.lstatSync(p);
  } catch (err) {
    return results;
  }

  // Read in files
  fs.readdirSync(p).forEach(function(file) {

    var stats, parsed;

    // Read file and stats
    file = path.join(p, file);
    stats = fs.lstatSync(file);

    // Recursively walk directory, or add file
    if (stats.isDirectory()) {
      if (recursive)
        results = results.concat(Utils.readDirectory(file, true))
    } else {
      parsed = path.parse(file);
      parsed.path = file;
      results.push(parsed);
    }

  });

  return results;

}

/*

 function readFileHead

 Reads a limited number of characters from a file.

*/

Utils.readFileHead = function(path, chars) {

  var buffer = new Buffer(chars),
      file   = fs.openSync(path, "r"),
      str,
      len;

  // Read in file
  len = fs.readSync(file, buffer, 0, chars, 0);

  // Convert to lines, and discard any fragments
  // (so that we can use template engines without through errors)
  str = buffer.slice(0, len).toString().split("\n");

  return str.slice(0, str.length - 1).join("\n")

}

/*

  function getRegExpMatches

*/

Utils.getRegExpMatches = function(str, re) {

  var match,
      matches = [];

  while (match = re.exec(str))
    matches.push(match[1]);

  return matches;

}

/*

  function watch

*/

Utils.watch = function(sourceDir, sourceExt, destExt) {

  if ("*" !== sourceExt) sourceExt = "*." + sourceExt.replace(/^[\*\.]+/g, "");
  if ("*" !== destExt) destExt = (destExt) ? ("*." + destExt.replace(/^[\*\.]+/g, "")) : sourceExt;

  global.server.watch(path.join(sourceDir, "**", sourceExt), function(event, file) {
    if ("change" === event) global.server.reload(destExt);
  });

}

<commit_msg>Utils#mapFiles: attaches basePath to file<commit_after>
/*

  Utils.js

*/

var __rootDir = process.cwd(),
    fs        = require("fs"),
    url       = require("url"),
    path      = require("path"),
    Utils;

module.exports = Utils = {};

/*

  function getRootPath

*/

Utils.getRootPath = function() {
  return __rootDir;
}

/*

  function makePathAbsolute

*/

Utils.makePathAbsolute = function(p) {

  return path.resolve(Utils.getRootPath(), p || "");

}

/*

  function isIndexFile

*/

Utils.isIndexFile = function(file) {
  return /index[^\/]*$/.test(file.name);
}

/*

  function mapFiles

*/

Utils.mapFiles = function(p, options) {

  var files, i, indices, results = [];
  options = options || {};

  // Make path absolute before call (for comparison after)
  p = Utils.makePathAbsolute(p);

  files = Utils.readDirectory(p, options.recursive);

  // Sort in reverse order so that directory calls come last. Then move "index" to end.
  if (options.sort) {
    files.sort(function(a, b) { return (a.path < b.path) ? -1 : (a.path > b.path) ? 1 : 0; }).reverse();
    i = files.length;
    while (i-- > 0)
      if (Utils.isIndexFile(files[i]))
        Array.prototype.push.apply(files, files.splice(i, 1));
  }

  // Remove subdirectory files if index.* is encountered
  if (options.bundleFolders) {

    indices = [];

    // Filter out index files (outside of master directory)
    i = files.length;
    while (i-- > 0) {
      if (Utils.isIndexFile(files[i]) && (p !== files[i].dir))
        Array.prototype.push.apply(indices, files.splice(i, 1));
    }

    // Remove indices that are subdirectories of each other
    i = indices.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++) {
        if (i !== j && 0 === indices[i].path.indexOf(indices[j].dir)) {
          indices.splice(i, 1);
          break;
        }
      }

    // Remove files in subdirectories of indices
    i = files.length;
    while (i-- > 0)
      for (var j = 0, n = indices.length; j < n; j++)
        if (0 === files[i].path.indexOf(indices[j].dir)) {
          files.splice(i, 1);
          break;
        }

    // Denote indices as bundles
    indices.forEach(function(file) { file.bundle = true });

    // Rejoin indices back into files
    files = files.concat(indices);

  }

  files.forEach(function(file) {
    if (!options.filter || options.filter.indexOf(file.ext) > -1) {
      file.basePath = p;
      file.folder = path.relative(p, file.path.replace(new RegExp(file.base + "$"), ""));
      results.push(file);
    }
  });

  return results;

}

/*

  function makeRoutes

*/

Utils.makeRoutes = function(route, file, options) {

  var base,
      routes,
      ext,
      options = options || {};

  // !!! WHAT TO DO ABOUT EXTENSIONLESS FILES?
  ext = options.type || file.ext;
  ext = ("undefined" == typeof ext) ? "" : ext.replace(/^\./, "");
  base = (url.resolve((route + "/").replace(/\/\/$/, "/"), file.folder) + "/").replace(/\/\/$/, "/");

  // Wildcard directories
  if ("html" === ext && options.query) {
    // If name starts with @, look for parent directory;
    if ("@" === file.name[0]) base = base.split("/").slice(0, -1).join("/")
    return [base + "/:slug"];
  }

  // Add file and default extension
  routes = [url.resolve(base, file.name + "." + ext)];

  // If the file is named "index", we allow it to function as the folder.
  if ("html" === ext && Utils.isIndexFile(file)) routes.push(base);

  return routes;

}

/*

  function readDirectory

*/

Utils.readDirectory = function(p, recursive) {

  var results = [];

  // Set defaults
  if ("undefined" == typeof recursive) recursive = true;
  p = Utils.makePathAbsolute(p);

  // If directory doesn't exist, return nothing
  try {
    fs.lstatSync(p);
  } catch (err) {
    return results;
  }

  // Read in files
  fs.readdirSync(p).forEach(function(file) {

    var stats, parsed;

    // Read file and stats
    file = path.join(p, file);
    stats = fs.lstatSync(file);

    // Recursively walk directory, or add file
    if (stats.isDirectory()) {
      if (recursive)
        results = results.concat(Utils.readDirectory(file, true))
    } else {
      parsed = path.parse(file);
      parsed.path = file;
      results.push(parsed);
    }

  });

  return results;

}

/*

 function readFileHead

 Reads a limited number of characters from a file.

*/

Utils.readFileHead = function(path, chars) {

  var buffer = new Buffer(chars),
      file   = fs.openSync(path, "r"),
      str,
      len;

  // Read in file
  len = fs.readSync(file, buffer, 0, chars, 0);

  // Convert to lines, and discard any fragments
  // (so that we can use template engines without through errors)
  str = buffer.slice(0, len).toString().split("\n");

  return str.slice(0, str.length - 1).join("\n")

}

/*

  function getRegExpMatches

*/

Utils.getRegExpMatches = function(str, re) {

  var match,
      matches = [];

  while (match = re.exec(str))
    matches.push(match[1]);

  return matches;

}

/*

  function watch

*/

Utils.watch = function(sourceDir, sourceExt, destExt) {

  if ("*" !== sourceExt) sourceExt = "*." + sourceExt.replace(/^[\*\.]+/g, "");
  if ("*" !== destExt) destExt = (destExt) ? ("*." + destExt.replace(/^[\*\.]+/g, "")) : sourceExt;

  global.server.watch(path.join(sourceDir, "**", sourceExt), function(event, file) {
    if ("change" === event) global.server.reload(destExt);
  });

}

<|endoftext|>