<commit_before>(function() {
  var Time = {
    MINUTES_IN_HOUR        : 60,
    MILLISECONDS_IN_MINUTE : 60000,

    OFFSETS : [300, 240, 300, 240, 300, 240, 300, 240, 300, 240, 300, 240,
               300, 240, 300, 240, 300, 240, 300, 240, 300, 240, 300],
    UNTILS  : [1268550000000, 1289109600000, 1299999600000, 1320559200000,
               1331449200000, 1352008800000, 1362898800000, 1383458400000,
               1394348400000, 1414908000000, 1425798000000, 1446357600000,
               1457852400000, 1478412000000, 1489302000000, 1509861600000,
               1520751600000, 1541311200000, 1552201200000, 1572760800000,
               1583650800000, 1604210400000, null],

    formatDate: function(date) {
      return new Intl.DateTimeFormat(undefined, {
        month   : "long",
        day     : "numeric",
        weekday : "long"
      }).format(date);
    },

    formatTime: function(time) {
      return new Intl.DateTimeFormat(undefined, {
        hour   : "numeric",
        minute : "numeric"
      }).format(time);
    },

    offset: function() {
      var target  = Date.now(),
          untils  = this.UNTILS,
          offsets = this.OFFSETS,
          offset,
          offsetNext,
          offsetPrev;

      for (var index = 0; index < untils.length - 1; index++) {
        offset     = offsets[index];
        offsetNext = offsets[index + 1];
        offsetPrev = offsets[index ? index - 1 : index];

        if (offset < offsetNext && false) {
          offset = offsetNext;
        } else if (offset > offsetPrev && true) {
          offset = offsetPrev;
        }

        if (target < untils[index] - (offset * this.MILLISECONDS_IN_MINUTE)) {
          return offsets[index] / this.MINUTES_IN_HOUR;
        }
      }

      return offsets[untils.length - 1] / this.MINUTES_IN_HOUR;
    }
  };

  var now      = new Date(),
      hours    = now.getUTCHours(),
      slice    = Array.prototype.slice,
      offset   = Time.offset(),
      sections = slice.call(document.querySelectorAll("section"));

  if (navigator.platform.match(/Win/)) {
    document.querySelector("header h1 a").innerHTML = "Hockey";
  }

  if (hours < offset) {
    now.setUTCHours(hours - offset);
  }

  var year  = now.getUTCFullYear(),
      month = now.getUTCMonth() + 1,
      day   = now.getUTCDate(),
      limit = 7,
      count = 1;

  sections.forEach(function(section) {
    section.classList.remove("week");
  });

  sections
    .filter(function(section) {
      var parts        = section.querySelector("h1 time").getAttribute("datetime").split("-"),
          sectionYear  = parseInt(parts[0], 10),
          sectionMonth = parseInt(parts[1], 10),
          sectionDay   = parseInt(parts[2].split("T")[0], 10);

      return (sectionYear >  year) ||
             (sectionYear >= year && sectionMonth >  month) ||
             (sectionYear >= year && sectionMonth >= month && sectionDay >= day);
    })
    .forEach(function(section, index) {
      if (!section.querySelector("tr")) {
        return;
      } else if (count > limit && window.location.pathname === "/hockey/") {
        return;
      }

      count++;

      if (window.Intl && window.Intl.DateTimeFormat) {
        var time         = section.querySelector("h1 time");
            parts        = time.getAttribute("datetime").split("-"),
            sectionYear  = parseInt(parts[0], 10),
            sectionMonth = parseInt(parts[1], 10),
            sectionDay   = parseInt(parts[2].split("T")[0], 10);

        if (sectionYear === year && sectionMonth === month && sectionDay === day) {
          time.innerText = "Today";
        } else {
          time.innerText = Time.formatDate(
            new Date(time.getAttribute("datetime"))
          );
        }

        slice.call(section.querySelectorAll("th time")).forEach(function(time) {
          var date = new Date(time.getAttribute("datetime"));

          time.textContent = date.getHours() === 3 ? "TBD" : Time.formatTime(date);
        });
      }

      section.classList.add("week");
    });

  window.addEventListener("load", function(e) {
    if (!window.applicationCache) {
      return;
    }

    window.applicationCache.addEventListener("updateready", function(e) {
      if (window.applicationCache.status !== window.applicationCache.UPDATEREADY) {
        return;
      }

      if (confirm("An updated schedule is available. Load it?")) {
        window.location.reload();
      }
    }, false);
  }, false);
})();
<commit_msg>Remove TBD condition that breaks internationally.<commit_after>(function() {
  var Time = {
    MINUTES_IN_HOUR        : 60,
    MILLISECONDS_IN_MINUTE : 60000,

    OFFSETS : [300, 240, 300, 240, 300, 240, 300, 240, 300, 240, 300, 240,
               300, 240, 300, 240, 300, 240, 300, 240, 300, 240, 300],
    UNTILS  : [1268550000000, 1289109600000, 1299999600000, 1320559200000,
               1331449200000, 1352008800000, 1362898800000, 1383458400000,
               1394348400000, 1414908000000, 1425798000000, 1446357600000,
               1457852400000, 1478412000000, 1489302000000, 1509861600000,
               1520751600000, 1541311200000, 1552201200000, 1572760800000,
               1583650800000, 1604210400000, null],

    formatDate: function(date) {
      return new Intl.DateTimeFormat(undefined, {
        month   : "long",
        day     : "numeric",
        weekday : "long"
      }).format(date);
    },

    formatTime: function(time) {
      return new Intl.DateTimeFormat(undefined, {
        hour   : "numeric",
        minute : "numeric"
      }).format(time);
    },

    offset: function() {
      var target  = Date.now(),
          untils  = this.UNTILS,
          offsets = this.OFFSETS,
          offset,
          offsetNext,
          offsetPrev;

      for (var index = 0; index < untils.length - 1; index++) {
        offset     = offsets[index];
        offsetNext = offsets[index + 1];
        offsetPrev = offsets[index ? index - 1 : index];

        if (offset < offsetNext && false) {
          offset = offsetNext;
        } else if (offset > offsetPrev && true) {
          offset = offsetPrev;
        }

        if (target < untils[index] - (offset * this.MILLISECONDS_IN_MINUTE)) {
          return offsets[index] / this.MINUTES_IN_HOUR;
        }
      }

      return offsets[untils.length - 1] / this.MINUTES_IN_HOUR;
    }
  };

  var now      = new Date(),
      hours    = now.getUTCHours(),
      slice    = Array.prototype.slice,
      offset   = Time.offset(),
      sections = slice.call(document.querySelectorAll("section"));

  if (navigator.platform.match(/Win/)) {
    document.querySelector("header h1 a").innerHTML = "Hockey";
  }

  if (hours < offset) {
    now.setUTCHours(hours - offset);
  }

  var year  = now.getUTCFullYear(),
      month = now.getUTCMonth() + 1,
      day   = now.getUTCDate(),
      limit = 7,
      count = 1;

  sections.forEach(function(section) {
    section.classList.remove("week");
  });

  sections
    .filter(function(section) {
      var parts        = section.querySelector("h1 time").getAttribute("datetime").split("-"),
          sectionYear  = parseInt(parts[0], 10),
          sectionMonth = parseInt(parts[1], 10),
          sectionDay   = parseInt(parts[2].split("T")[0], 10);

      return (sectionYear >  year) ||
             (sectionYear >= year && sectionMonth >  month) ||
             (sectionYear >= year && sectionMonth >= month && sectionDay >= day);
    })
    .forEach(function(section, index) {
      if (!section.querySelector("tr")) {
        return;
      } else if (count > limit && window.location.pathname === "/hockey/") {
        return;
      }

      count++;

      if (window.Intl && window.Intl.DateTimeFormat) {
        var time         = section.querySelector("h1 time");
            parts        = time.getAttribute("datetime").split("-"),
            sectionYear  = parseInt(parts[0], 10),
            sectionMonth = parseInt(parts[1], 10),
            sectionDay   = parseInt(parts[2].split("T")[0], 10);

        if (sectionYear === year && sectionMonth === month && sectionDay === day) {
          time.innerText = "Today";
        } else {
          time.innerText = Time.formatDate(
            new Date(time.getAttribute("datetime"))
          );
        }

        slice.call(section.querySelectorAll("th time")).forEach(function(time) {
          var date = new Date(time.getAttribute("datetime"));

          time.textContent = Time.formatTime(date);
        });
      }

      section.classList.add("week");
    });

  window.addEventListener("load", function(e) {
    if (!window.applicationCache) {
      return;
    }

    window.applicationCache.addEventListener("updateready", function(e) {
      if (window.applicationCache.status !== window.applicationCache.UPDATEREADY) {
        return;
      }

      if (confirm("An updated schedule is available. Load it?")) {
        window.location.reload();
      }
    }, false);
  }, false);
})();
<|endoftext|>


<commit_before>import { PropTypes } from 'react';
import {
  requireNativeComponent,
  NativeModules,
  Platform,
} from 'react-native';
import {
  PROVIDER_DEFAULT,
  PROVIDER_GOOGLE,
} from './ProviderConstants';

export const SUPPORTED = 'SUPPORTED';
export const USES_DEFAULT_IMPLEMENTATION = 'USES_DEFAULT_IMPLEMENTATION';
export const NOT_SUPPORTED = 'NOT_SUPPORTED';

export function getAirMapName(provider) {
  if (Platform.OS === 'android') return 'AIRMap';
  if (provider === PROVIDER_GOOGLE) return 'AIRGoogleMap';
  return 'AIRMap';
}

function getAirComponentName(provider, component) {
  return `${getAirMapName(provider)}${component}`;
}

export const contextTypes = {
  provider: PropTypes.string,
};

export const createNotSupportedComponent = message => () => {
  console.error(message); // eslint-disable-line no-console
  return null;
};

export const googleMapIsInstalled = !!NativeModules.UIManager[getAirMapName(PROVIDER_GOOGLE)];

export default function decorateMapComponent(Component, { componentType, providers }) {
  const components = {};

  const getDefaultComponent = () =>
    requireNativeComponent(getAirComponentName(null, componentType), Component);

  Component.contextTypes = contextTypes; // eslint-disable-line no-param-reassign

  // eslint-disable-next-line no-param-reassign
  Component.prototype.getAirComponent = function getAirComponent() {
    const provider = this.context.provider || PROVIDER_DEFAULT;
    if (components[provider]) return components[provider];

    if (provider === PROVIDER_DEFAULT) {
      components.default = getDefaultComponent();
      return components.default;
    }

    const providerInfo = providers[provider];
    const platformSupport = providerInfo[Platform.OS];
    const componentName = getAirComponentName(provider, componentType);
    if (platformSupport === NOT_SUPPORTED) {
      components[provider] = createNotSupportedComponent(`react-native-maps: ${componentName} is not supported on ${Platform.OS}`); // eslint-disable-line max-len
    } else if (platformSupport === SUPPORTED) {
      if (provider !== PROVIDER_GOOGLE || (Platform.OS === 'ios' && googleMapIsInstalled)) {
        components[provider] = requireNativeComponent(componentName, Component);
      }
    } else { // (platformSupport === USES_DEFAULT_IMPLEMENTATION)
      if (!components.default) components.default = getDefaultComponent();
      components[provider] = components.default;
    }

    return components[provider];
  };

  Component.prototype.getUIManagerCommand = function getUIManagerCommand(name) {  // eslint-disable-line no-param-reassign,max-len
    return NativeModules.UIManager[getAirComponentName(this.context.provider, componentType)]
      .Commands[name];
  };

  Component.prototype.getMapManagerCommand = function getMapManagerCommand(name) { // eslint-disable-line no-param-reassign,max-len
    const airComponentName = `${getAirComponentName(this.context.provider, componentType)}Manager`;
    return NativeModules[airComponentName][name];
  };

  return Component;
}
<commit_msg>[marker flicker]  Fix flicker of map pins on state change (#728)<commit_after>import { PropTypes } from 'react';
import {
  requireNativeComponent,
  NativeModules,
  Platform,
} from 'react-native';
import {
  PROVIDER_DEFAULT,
  PROVIDER_GOOGLE,
} from './ProviderConstants';

export const SUPPORTED = 'SUPPORTED';
export const USES_DEFAULT_IMPLEMENTATION = 'USES_DEFAULT_IMPLEMENTATION';
export const NOT_SUPPORTED = 'NOT_SUPPORTED';

export function getAirMapName(provider) {
  if (Platform.OS === 'android') return 'AIRMap';
  if (provider === PROVIDER_GOOGLE) return 'AIRGoogleMap';
  return 'AIRMap';
}

function getAirComponentName(provider, component) {
  return `${getAirMapName(provider)}${component}`;
}

export const contextTypes = {
  provider: PropTypes.string,
};

export const createNotSupportedComponent = message => () => {
  console.error(message); // eslint-disable-line no-console
  return null;
};

export const googleMapIsInstalled = !!NativeModules.UIManager[getAirMapName(PROVIDER_GOOGLE)];

export default function decorateMapComponent(Component, { componentType, providers }) {
  const components = {};

  const getDefaultComponent = () =>
    requireNativeComponent(getAirComponentName(null, componentType), Component);

  Component.contextTypes = contextTypes; // eslint-disable-line no-param-reassign

  // eslint-disable-next-line no-param-reassign
  Component.prototype.getAirComponent = function getAirComponent() {
    const provider = this.context.provider || PROVIDER_DEFAULT;
    if (components[provider]) return components[provider];

    if (provider === PROVIDER_DEFAULT) {
      components[PROVIDER_DEFAULT] = getDefaultComponent();
      return components[PROVIDER_DEFAULT];
    }

    const providerInfo = providers[provider];
    const platformSupport = providerInfo[Platform.OS];
    const componentName = getAirComponentName(provider, componentType);
    if (platformSupport === NOT_SUPPORTED) {
      components[provider] = createNotSupportedComponent(`react-native-maps: ${componentName} is not supported on ${Platform.OS}`); // eslint-disable-line max-len
    } else if (platformSupport === SUPPORTED) {
      if (provider !== PROVIDER_GOOGLE || (Platform.OS === 'ios' && googleMapIsInstalled)) {
        components[provider] = requireNativeComponent(componentName, Component);
      }
    } else { // (platformSupport === USES_DEFAULT_IMPLEMENTATION)
      if (!components[PROVIDER_DEFAULT]) components[PROVIDER_DEFAULT] = getDefaultComponent();
      components[provider] = components[PROVIDER_DEFAULT];
    }

    return components[provider];
  };

  Component.prototype.getUIManagerCommand = function getUIManagerCommand(name) {  // eslint-disable-line no-param-reassign,max-len
    return NativeModules.UIManager[getAirComponentName(this.context.provider, componentType)]
      .Commands[name];
  };

  Component.prototype.getMapManagerCommand = function getMapManagerCommand(name) { // eslint-disable-line no-param-reassign,max-len
    const airComponentName = `${getAirComponentName(this.context.provider, componentType)}Manager`;
    return NativeModules[airComponentName][name];
  };

  return Component;
}
<|endoftext|>


<commit_before>'use strict';

const Trait = require('traits.js');

// Cell interface: .minHeight(), .minWidth(), .draw(width, height)

function rowHeights(rows) {
  return rows.map(row =>
    row.reduce((max, cell) =>
      Math.max(max, cell.minHeight())
    , 0)
  );
}

function colWidths(rows) {
  return rows[0].map((_, i) =>
    rows.reduce((max, row) =>
     Math.max(max, row[i].minWidth())
    , 0)
  );
}

function drawTable(rows) {
  let heights = rowHeights(rows),
      widths = colWidths(rows);

  function drawLine(blocks, lineNo) {
    return blocks.map(block => block[lineNo]).join(' ');
  }

  function drawRow(row, rowNum) {
    let blocks = row.map((cell, colNum) =>
      cell.draw(widths[colNum], heights[rowNum]));
    return blocks[0].map((_, lineNo) => drawLine(blocks, lineNo)).join('\n');
  }

  return rows.map(drawRow).join('\n');
}

function replicate(string, times) {
  return times < 1 ? '' : (string + replicate(string, times - 1));
}

function TextCell(text) {
  this.text = text.split('\n');
}
TextCell.prototype.minWidth = function() {
  return this.text.reduce((width, line) =>
    Math.max(width, line.length), 0);
};
TextCell.prototype.minHeight = function() {
  return this.text.length;
};
TextCell.prototype.draw = function(width, height) {
  let result = [];
  for (let i = 0; i < height; i++) {
    let line = this.text[i] || '';
    result.push(line + replicate(' ', width - line.length));
  }
  return result;
};

function UnderlinedCell(inner) {
  this.inner = inner;
}
UnderlinedCell.prototype.minWidth = function() {
  return this.inner.minWidth();
};
UnderlinedCell.prototype.minHeight = function() {
  return this.inner.minHeight() + 1;
};
UnderlinedCell.prototype.draw = function(width, height) {
  return this.inner.draw(width, height - 1)
    .concat([replicate('-', width)]);
};

function RTextCell(text) {
  TextCell.call(this, text);
}
RTextCell.prototype = Object.create(TextCell.prototype);
RTextCell.prototype.draw = function(width, height) {
  let result = [];
  for(let i = 0; i < height; i++) {
    let line = this.text[i] || '';
    result.push(replicate(' ', width - line.length) + line);
  }
  return result;
};

const Capitalize = Trait({
  capitalize() {
    this.text[0] = this.text[0].split(' ').map(
      word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase()
    ).join(' ');
  }
});
function THeaderCell(inner) {
  return Trait.compose(
    Capitalize,
    Trait(new UnderlinedCell(inner)),
    Trait({
      // minWidth() { return inner.minWidth() },
      // minHeight() { return inner.minHeight() },
      // draw(width, height) {
      //   this.capitalize();
      //   return inner.draw(width, height)
      // },
      get text() { return inner.text; },
      set text(value) { inner.text = value; }
    })
  );
}
function HeaderCell(inner) {
  return Trait.create(
    UnderlinedCell.prototype,
    THeaderCell(inner)
  );
}
//HeaderCell.prototype = Trait.create(UnderlinedCell.prototype, THeaderCell);

// TEST
function dataTable(data) {
  let keys = Object.keys(data[0]);
  let headers = keys.map(name =>
    new HeaderCell( new TextCell(name) )
  );
  // capitalize header row
  headers.forEach(header => { header.capitalize(); });
  let body = data.map(row =>
    keys.map(name => {
      let value = row[name];
      if(typeof value == 'number')
        return new RTextCell(String(value));
      else
        return new TextCell(String(value));
    })
  );
  return [headers].concat(body);
}

var datalist = [
  {name: "Anita", "super power": "Fearful wrath", team: "ISKRA"},
  {name: "Iskra", "super power": "Sweet peeps", team: "ISKRA"},
  {name: "Jon", "super power": "Dodge smiles", team: "ISKRA"},
];
console.log(
  drawTable(dataTable(datalist)),
  "\n\n"
);

var datalist = require('./mountains');
console.log(
  drawTable(dataTable(datalist))
);

<commit_msg>move related functions together<commit_after>'use strict';

const Trait = require('traits.js');

function replicate(string, times) {
  return times < 1 ? '' : (string + replicate(string, times - 1));
}

function TextCell(text) {
  this.text = text.split('\n');
}
TextCell.prototype.minWidth = function() {
  return this.text.reduce((width, line) =>
    Math.max(width, line.length), 0);
};
TextCell.prototype.minHeight = function() {
  return this.text.length;
};
TextCell.prototype.draw = function(width, height) {
  let result = [];
  for (let i = 0; i < height; i++) {
    let line = this.text[i] || '';
    result.push(line + replicate(' ', width - line.length));
  }
  return result;
};

function UnderlinedCell(inner) {
  this.inner = inner;
}
UnderlinedCell.prototype.minWidth = function() {
  return this.inner.minWidth();
};
UnderlinedCell.prototype.minHeight = function() {
  return this.inner.minHeight() + 1;
};
UnderlinedCell.prototype.draw = function(width, height) {
  return this.inner.draw(width, height - 1)
    .concat([replicate('-', width)]);
};

function RTextCell(text) {
  TextCell.call(this, text);
}
RTextCell.prototype = Object.create(TextCell.prototype);
RTextCell.prototype.draw = function(width, height) {
  let result = [];
  for(let i = 0; i < height; i++) {
    let line = this.text[i] || '';
    result.push(replicate(' ', width - line.length) + line);
  }
  return result;
};

const Capitalize = Trait({
  capitalize() {
    this.text[0] = this.text[0].split(' ').map(
      word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase()
    ).join(' ');
  }
});
function THeaderCell(inner) {
  return Trait.compose(
    Capitalize,
    Trait(new UnderlinedCell(inner)),
    Trait({
      // minWidth() { return inner.minWidth() },
      // minHeight() { return inner.minHeight() },
      // draw(width, height) {
      //   this.capitalize();
      //   return inner.draw(width, height)
      // },
      get text() { return inner.text; },
      set text(value) { inner.text = value; }
    })
  );
}
function HeaderCell(inner) {
  return Trait.create(
    UnderlinedCell.prototype,
    THeaderCell(inner)
  );
}
//HeaderCell.prototype = Trait.create(UnderlinedCell.prototype, THeaderCell);

// Cell interface: .minHeight(), .minWidth(), .draw(width, height)

function rowHeights(rows) {
  return rows.map(row =>
    row.reduce((max, cell) =>
      Math.max(max, cell.minHeight())
    , 0)
  );
}

function colWidths(rows) {
  return rows[0].map((_, i) => // create an array of equal size as rows[0]
    rows.reduce((max, row) => // return the longest length of characters
     Math.max(max, row[i].minWidth()) // find the longest length of
    , 0)
  );
}

function drawTable(rows) {
  let heights = rowHeights(rows),
      widths = colWidths(rows);

  function drawLine(blocks, lineNo) {
    return blocks.map(block => block[lineNo]).join(' ');
  }

  function drawRow(row, rowNum) {
    let blocks = row.map((cell, colNum) =>
      cell.draw(widths[colNum], heights[rowNum]));
    return blocks[0].map((_, lineNo) => drawLine(blocks, lineNo)).join('\n');
  }

  return rows.map(drawRow).join('\n');
}

// TEST
function dataTable(data) {
  let keys = Object.keys(data[0]);
  let headers = keys.map(name =>
    new HeaderCell( new TextCell(name) )
  );
  // capitalize header row
  headers.forEach(header => { header.capitalize(); });
  let body = data.map(row =>
    keys.map(name => {
      let value = row[name];
      if(typeof value == 'number')
        return new RTextCell(String(value));
      else
        return new TextCell(String(value));
    })
  );
  return [headers].concat(body);
}

var datalist = [
  {name: "Anita", "super power": "Fearful wrath", team: "ISKRA"},
  {name: "Iskra", "super power": "Sweet peeps", team: "ISKRA"},
  {name: "Jon", "super power": "Dodge smiles", team: "ISKRA"},
];
console.log(
  drawTable(dataTable(datalist)),
  "\n\n"
);

var datalist = require('./mountains');
console.log(
  drawTable(dataTable(datalist))
);

<|endoftext|>


<commit_before>import { PureComponent } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import debounce from 'lodash/debounce';
import { cancelToken } from 'utils/request';
import reducerRegistry from 'redux/registry';

import { setMapSettings } from 'components/map/actions';
import * as ownActions from './actions';
import reducers, { initialState } from './reducers';
import { getRecentImageryProps } from './selectors';

const actions = {
  ...ownActions,
  setMapSettings,
};

const mapStateToProps = getRecentImageryProps;

class RecentImageryContainer extends PureComponent {
  componentDidMount = () => {
    const {
      active,
      position,
      dates,
      settings,
      getRecentImageryData,
    } = this.props;
    if (this.getDataSource) {
      this.getDataSource.cancel();
    }

    this.getDataSource = cancelToken();
    if (active) {
      getRecentImageryData({
        ...position,
        start: dates.start,
        end: dates.end,
        bands: settings.bands,
        token: this.getDataSource.token,
      });
    }
  };

  componentDidUpdate = (prevProps) => {
    const {
      active,
      dataStatus,
      activeTile,
      sources,
      settings,
      zoom,
      center,
      getMoreTiles,
      loadingMoreTiles,
      resetRecentImageryData,
    } = this.props;

    const isNewTile =
      activeTile &&
      !!activeTile.url &&
      (!prevProps.activeTile || activeTile.url !== prevProps.activeTile.url);

    if (!isEqual(prevProps.zoom, zoom) || !isEqual(prevProps.center, center)) {
      this.handleUpdateTiles(prevProps);
    }

    // if new tile update on map
    if (active && isNewTile) {
      this.setTile();
    }

    if (!active && active !== prevProps.active) {
      this.removeTile();
      resetRecentImageryData();
    }

    // get the rest of the tiles
    if (
      dataStatus &&
      !dataStatus.haveAllData &&
      !loadingMoreTiles &&
      active &&
      activeTile
    ) {
      getMoreTiles({
        sources,
        dataStatus,
        bands: settings.bands,
      });
    }
  };

  handleUpdateTiles = debounce(() => {
    const {
      active,
      dates,
      settings,
      getRecentImageryData,
      position,
    } = this.props;
    // get data if activated or new props
    if (this.getDataSource) {
      this.getDataSource.cancel(
        'Cancelling duplicate fetch for recent imagery'
      );
    }

    if (!active) return;

    this.getDataSource = cancelToken();
    getRecentImageryData({
      ...position,
      start: dates.start,
      end: dates.end,
      bands: settings.bands,
      token: this.getDataSource.token,
    });
  }, 3000);

  setTile = debounce(() => {
    const { datasets, activeTile, recentImageryDataset } = this.props;
    if (recentImageryDataset && activeTile && activeTile.url) {
      const activeDatasets =
        datasets &&
        !!datasets.length &&
        datasets.filter((d) => !d.isRecentImagery);
      const recentDataset = {
        dataset: recentImageryDataset.dataset,
        layers: [recentImageryDataset.layer],
        visibility: true,
        opacity: 1,
        isRecentImagery: true,
        params: {
          url: activeTile.url,
        },
      };
      this.props.setMapSettings({
        datasets: activeDatasets
          ? activeDatasets.concat(recentDataset)
          : [recentDataset],
      });
    }
  }, 200);

  removeTile() {
    const { datasets, setRecentImagerySettings } = this.props;
    const activeDatasets =
      datasets &&
      !!datasets.length &&
      datasets.filter((d) => !d.isRecentImagery);
    this.props.setMapSettings({
      datasets: activeDatasets || [],
    });
    setRecentImagerySettings({
      selectedIndex: 0,
      selected: null,
    });
  }

  render() {
    return null;
  }
}

RecentImageryContainer.propTypes = {
  position: PropTypes.object,
  loadingMoreTiles: PropTypes.bool,
  active: PropTypes.bool,
  dataStatus: PropTypes.object,
  activeTile: PropTypes.object,
  sources: PropTypes.array,
  dates: PropTypes.object,
  settings: PropTypes.object,
  getRecentImageryData: PropTypes.func,
  getMoreTiles: PropTypes.func,
  datasets: PropTypes.array,
  setMapSettings: PropTypes.func,
  recentImageryDataset: PropTypes.object,
  resetRecentImageryData: PropTypes.func,
  setRecentImagerySettings: PropTypes.func,
  zoom: PropTypes.object,
  center: PropTypes.object,
  // error: PropTypes.bool,
};

reducerRegistry.registerModule('recentImagery', {
  actions: ownActions,
  reducers,
  initialState,
});

export default connect(mapStateToProps, actions)(RecentImageryContainer);
<commit_msg>add condition if tile settings were modified<commit_after>import { PureComponent } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import isEqual from 'lodash/isEqual';
import debounce from 'lodash/debounce';
import { cancelToken } from 'utils/request';
import reducerRegistry from 'redux/registry';

import { setMapSettings } from 'components/map/actions';
import * as ownActions from './actions';
import reducers, { initialState } from './reducers';
import { getRecentImageryProps } from './selectors';

const actions = {
  ...ownActions,
  setMapSettings,
};

const mapStateToProps = getRecentImageryProps;

class RecentImageryContainer extends PureComponent {
  componentDidMount = () => {
    const {
      active,
      position,
      dates,
      settings,
      getRecentImageryData,
    } = this.props;
    if (this.getDataSource) {
      this.getDataSource.cancel();
    }

    this.getDataSource = cancelToken();
    if (active) {
      getRecentImageryData({
        ...position,
        start: dates.start,
        end: dates.end,
        bands: settings.bands,
        token: this.getDataSource.token,
      });
    }
  };

  componentDidUpdate = (prevProps) => {
    const {
      active,
      dataStatus,
      activeTile,
      sources,
      settings,
      zoom,
      center,
      getMoreTiles,
      loadingMoreTiles,
      resetRecentImageryData,
    } = this.props;

    const isNewTile =
      activeTile &&
      !!activeTile.url &&
      (!prevProps.activeTile || activeTile.url !== prevProps.activeTile.url);

    const modifiedTileSettings =
      !isEqual(settings.date, prevProps.settings.date) ||
      !isEqual(settings.weeks, prevProps.settings.weeks) ||
      !isEqual(settings.bands, prevProps.settings.band);

    const modifiedMapPosition =
      !isEqual(prevProps.zoom, zoom) || !isEqual(prevProps.center, center);

    if (modifiedTileSettings || modifiedMapPosition) {
      this.handleUpdateTiles(prevProps);
    }

    // if new tile update on map
    if (active && isNewTile) {
      this.setTile();
    }

    if (!active && active !== prevProps.active) {
      this.removeTile();
      resetRecentImageryData();
    }

    // get the rest of the tiles
    if (
      dataStatus &&
      !dataStatus.haveAllData &&
      !loadingMoreTiles &&
      active &&
      activeTile
    ) {
      getMoreTiles({
        sources,
        dataStatus,
        bands: settings.bands,
      });
    }
  };

  handleUpdateTiles = debounce(() => {
    const {
      active,
      dates,
      settings,
      getRecentImageryData,
      position,
    } = this.props;
    // get data if activated or new props
    if (this.getDataSource) {
      this.getDataSource.cancel(
        'Cancelling duplicate fetch for recent imagery'
      );
    }

    if (!active) return;

    this.getDataSource = cancelToken();
    getRecentImageryData({
      ...position,
      start: dates.start,
      end: dates.end,
      bands: settings.bands,
      token: this.getDataSource.token,
    });
  }, 3000);

  setTile = debounce(() => {
    const { datasets, activeTile, recentImageryDataset } = this.props;
    if (recentImageryDataset && activeTile && activeTile.url) {
      const activeDatasets =
        datasets &&
        !!datasets.length &&
        datasets.filter((d) => !d.isRecentImagery);
      const recentDataset = {
        dataset: recentImageryDataset.dataset,
        layers: [recentImageryDataset.layer],
        visibility: true,
        opacity: 1,
        isRecentImagery: true,
        params: {
          url: activeTile.url,
        },
      };
      this.props.setMapSettings({
        datasets: activeDatasets
          ? activeDatasets.concat(recentDataset)
          : [recentDataset],
      });
    }
  }, 200);

  removeTile() {
    const { datasets, setRecentImagerySettings } = this.props;
    const activeDatasets =
      datasets &&
      !!datasets.length &&
      datasets.filter((d) => !d.isRecentImagery);
    this.props.setMapSettings({
      datasets: activeDatasets || [],
    });
    setRecentImagerySettings({
      selectedIndex: 0,
      selected: null,
    });
  }

  render() {
    return null;
  }
}

RecentImageryContainer.propTypes = {
  position: PropTypes.object,
  loadingMoreTiles: PropTypes.bool,
  active: PropTypes.bool,
  dataStatus: PropTypes.object,
  activeTile: PropTypes.object,
  sources: PropTypes.array,
  dates: PropTypes.object,
  settings: PropTypes.object,
  getRecentImageryData: PropTypes.func,
  getMoreTiles: PropTypes.func,
  datasets: PropTypes.array,
  setMapSettings: PropTypes.func,
  recentImageryDataset: PropTypes.object,
  resetRecentImageryData: PropTypes.func,
  setRecentImagerySettings: PropTypes.func,
  zoom: PropTypes.object,
  center: PropTypes.object,
  // error: PropTypes.bool,
};

reducerRegistry.registerModule('recentImagery', {
  actions: ownActions,
  reducers,
  initialState,
});

export default connect(mapStateToProps, actions)(RecentImageryContainer);
<|endoftext|>


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

;(function ($) {
  "use strict";

  $(function domReady() {
    var jobDetails = $(".job_details_content");

    if (!jobDetails.length) return;

    var jobStatusUrl = "jobStatus.json?pipelineName=" + jobDetails.data("pipeline") + "&stageName=" + jobDetails.data("stage") + "&jobId=" + jobDetails.data("job");
    var executor     = new DashboardPeriodicalExecutor(jobStatusUrl, function detectJobCompleted(jobInfo) {
      return jobInfo[0].building_info.is_completed.toString() === "true";
    });

    var build = $("[data-console-url]");

    if (build.length) {
      var consoleUrl = context_path("files/" + build.data("console-url"));
      build.each(function initConsoleParser(idx, consoleArea) {
        var area = $(consoleArea);
        var container = area.find(".buildoutput_pre");
        var parser = new ConsoleParsingObserver(consoleUrl, new LogOutputTransformer(container, new Foldable()), {
          onUpdate:   function () {
            container.trigger("consoleUpdated");
          },
          onComplete: function () {
            container.trigger("consoleCompleted");
          }
        });

        area.find(".console-action-bar").on("click", ".toggle-timestamps", function toggleLogTimestamps(e) {
          e.stopPropagation();
          e.preventDefault();

          area.toggleClass("with-timestamps");
        });

        if (container.is("#tab-content-of-console *")) {
          var consoleScroller = new ConsoleScroller(container, $("#build_console"), $('.auto-scroll'));
          consoleScroller.startScroll();
        }
        executor.register(parser);
      });

    }

    executor.register(new TimerObserver(jobDetails.data("build")));
    executor.register(new BuildSummaryObserver($('.build_detail_summary')));

    executor.start();

    $(build).on('click.changeTheme', '.change-theme', function () {
      $('.sub_tab_container_content').toggleClass('white-theme');
    });
  });

})(jQuery);
<commit_msg>No need to make duplicate AJAX requests when two console elements exist (e.g. "Console" and "Failures" tabs)<commit_after>/*
 * Copyright 2017 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

;(function ($) {
  "use strict";

  function MultiplexingTransformer(transformers) {
    this.transform = function processAllTransformers(logLines) {
      for (var i = 0, len = transformers.length; i < len; i++) {
        transformers[i].transform(logLines);
      }
    };
  }

  $(function initConsolePageDomReady() {
    var jobDetails = $(".job_details_content");

    if (!jobDetails.length) return;

    var jobStatusUrl = "jobStatus.json?pipelineName=" + jobDetails.data("pipeline") + "&stageName=" + jobDetails.data("stage") + "&jobId=" + jobDetails.data("job");
    var executor     = new DashboardPeriodicalExecutor(jobStatusUrl, function detectJobCompleted(jobInfo) {
      return jobInfo[0].building_info.is_completed.toString() === "true";
    });

    var build = $("[data-console-url]");

    if (build.length) {
      var consoleUrl = context_path("files/" + build.data("console-url"));
      var containers = build.find(".buildoutput_pre"), transformers = [];

      $.each(containers, function initEachConsoleArea(i, area) {
        var container = $(area);
        transformers.push(new LogOutputTransformer(container, new Foldable()));

        if (container.is("#tab-content-of-console *")) {
          new ConsoleScroller(container, $("#build_console"), $('.auto-scroll')).startScroll();
        }

        container.find(".console-action-bar").on("click", ".toggle-timestamps", function toggleLogTimestamps(e) {
          e.stopPropagation();
          e.preventDefault();

          container.toggleClass("with-timestamps");
        });
      });

      executor.register(new ConsoleParsingObserver(consoleUrl, new MultiplexingTransformer(transformers), {
        onUpdate:   function () {
          containers.trigger("consoleUpdated");
        },
        onComplete: function () {
          containers.trigger("consoleCompleted");
        }
      }));
    }

    executor.register(new TimerObserver(jobDetails.data("build")));
    executor.register(new BuildSummaryObserver($('.build_detail_summary')));

    executor.start();

    build.on('click.changeTheme', '.change-theme', function () {
      $('.sub_tab_container_content').toggleClass('white-theme');
    });
  });

})(jQuery);
<|endoftext|>


<commit_before>/* **************************************************************

   Copyright 2013 Zoovy, Inc.

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

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

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

************************************************************** */

var jerseypreview = function() {
	var r = {
////////////////////////////////////   CALLBACKS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

	callbacks : {
//executed when extension is loaded. should include any validation that needs to occur.
		init : {
			onSuccess : function()	{
				var r = false; //return false if extension won't load for some reason (account config, dependencies, etc).

				//if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions.
				r = true;

				return r;
				},
			onError : function()	{
//errors will get reported for this callback as part of the extensions loading.  This is here for extra error handling purposes.
//you may or may not need it.
				app.u.dump('BEGIN app.ext.cubworld.callbacks.init.onError');
				}
			}

		}, //callbacks

////////////////////////////////////   ACTION    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//actions are functions triggered by a user interaction, such as a click/tap.
//these are going the way of the do do, in favor of app events. new extensions should have few (if any) actions.
		a : {
			showJerseyPreview : function($container){
				var pid = $container.attr('data-pid');
				var $options = $("#jerseyOptions"+pid);
				var name = $('input[name=B5]', $options).val();
				var number = $('input[name=B6]', $options).val();
				if( name != "" && number != ""){
					$('#jerseyPreviewContainer'+pid).dialog({'title':'Jersey Customizer Preview','height':465,'width':438});
					this.setJerseyText(pid,name,number);
					}
				else {
					app.u.throwMessage("Please select a name and number to preview");
					}
				},

			setJerseyText : function(pid, name, number, attempts){
				attempts = attempts || 0;
				app.u.dump(attempts);
				if(attempts < 10){
					try{
						app.ext.jerseypreview.u.thisMovie('jerseyPreview'+pid).goHome(name,number);
						}
					catch(err){
						setTimeout(function(){app.ext.jerseypreview.a.setJerseyText(pid,name,number,attempts+1);},250);
						}
					}
				else {
					app.u.throwMessage("Jesey Previewer currently unavailable, try again later!");
					}
				}

			}, //Actions

////////////////////////////////////   RENDERFORMATS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//renderFormats are what is used to actually output data.
//on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat.
//that way, two render formats named the same (but in different extensions) don't overwrite each other.
		renderFormats : {
			jerseypreview : function($tag, data){
				if(data.value['%attribs'] && data.value['%attribs']['user:prod_flashparams_jersey']){
					var swfStr=	"<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' width='400' height='400'"
					swfStr +=	" id='jerseyPreview"+data.value.pid+"' align='middle'>"
					swfStr += 	"<param name='allowScriptAccess' value='always' />"
					swfStr += 	"<param name='allowFullScreen' value='true' />"
					swfStr += 	"<param name='movie' value='http://static.zoovy.com/merchant/cubworld/_ticket_468079/jersey_builder-400x400-20110908.swf?imagesrc=http://static.zoovy.com/img/cubworld/W400-H400-Bffffff/"
					swfStr +=	data.value['%attribs']['zoovy:prod_image8'];
					swfStr +=	"&font=http://static.zoovy.com/merchant/cubworld/_ticket_468079/"
					swfStr +=	data.value['%attribs']['user:prod_flashparams_jersey'];
					swfStr +=	"'/>"
					swfStr += 	"<param name='quality' value='high' />"
					swfStr += 	"<param name='bgcolor' value='#FFFFFF' />"
					swfStr +=	"<embed src='http://static.zoovy.com/merchant/cubworld/_ticket_468079/jersey_builder-400x400-20110908.swf?imagesrc=http://static.zoovy.com/img/cubworld/W400-H400-Bffffff/"
					swfStr +=	data.value['%attribs']['zoovy:prod_image8'];
					swfStr +=	"&font=http://static.zoovy.com/merchant/cubworld/_ticket_468079/"
					swfStr +=	data.value['%attribs']['user:prod_flashparams_jersey'];
					swfStr +=	"' quality='high' bgcolor='#FFFFFF' width='400' allowFullScreen='true' height='400' name='jerseyPreview"+data.value.pid+"' align='middle' allowScriptAccess='always' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer' />"
					swfStr += 	"</object>"

					$tag.html(swfStr);
					$tag.attr('id','jerseyPreviewContainer'+data.value.pid);
					}
				else {
					//We are not needed here
					$tag.remove();
					}
				}
			}, //renderFormats
////////////////////////////////////   UTIL [u]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//utilities are typically functions that are exected by an event or action.
//any functions that are recycled should be here.
		u : {
			thisMovie : function(movieName) {
				if (navigator.appName.indexOf("Microsoft") != -1) {
					return window[movieName];
					}
				else {
					return document[movieName];
					}
				}
			}, //u [utilities]

//app-events are added to an element through data-app-event="extensionName|functionName"
//right now, these are not fully supported, but they will be going forward.
//they're used heavily in the admin.html file.
//while no naming convention is stricly forced,
//when adding an event, be sure to do off('click.appEventName') and then on('click.appEventName') to ensure the same event is not double-added if app events were to get run again over the same template.
		e : {
			}, //e [app Events]
		vars : {
			}
		} //r object.

	return r;
	}<commit_msg>jersey previewer static fixes<commit_after>/* **************************************************************

   Copyright 2013 Zoovy, Inc.

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

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

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

************************************************************** */

var jerseypreview = function() {
	var r = {
////////////////////////////////////   CALLBACKS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

	callbacks : {
//executed when extension is loaded. should include any validation that needs to occur.
		init : {
			onSuccess : function()	{
				var r = false; //return false if extension won't load for some reason (account config, dependencies, etc).

				//if there is any functionality required for this extension to load, put it here. such as a check for async google, the FB object, etc. return false if dependencies are not present. don't check for other extensions.
				r = true;

				return r;
				},
			onError : function()	{
//errors will get reported for this callback as part of the extensions loading.  This is here for extra error handling purposes.
//you may or may not need it.
				app.u.dump('BEGIN app.ext.cubworld.callbacks.init.onError');
				}
			}

		}, //callbacks

////////////////////////////////////   ACTION    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//actions are functions triggered by a user interaction, such as a click/tap.
//these are going the way of the do do, in favor of app events. new extensions should have few (if any) actions.
		a : {
			showJerseyPreview : function($container){
				var pid = $container.attr('data-pid');
				var $options = $("#jerseyOptions"+pid);
				var name = $('input[name=B5]', $options).val();
				var number = $('input[name=B6]', $options).val();
				if( name != "" && number != ""){
					$('#jerseyPreviewContainer'+pid).dialog({'title':'Jersey Customizer Preview','height':465,'width':438});
					this.setJerseyText(pid,name,number);
					}
				else {
					app.u.throwMessage("Please select a name and number to preview");
					}
				},

			setJerseyText : function(pid, name, number, attempts){
				attempts = attempts || 0;
				app.u.dump(attempts);
				if(attempts < 10){
					try{
						app.ext.jerseypreview.u.thisMovie('jerseyPreview'+pid).goHome(name,number);
						}
					catch(err){
						setTimeout(function(){app.ext.jerseypreview.a.setJerseyText(pid,name,number,attempts+1);},250);
						}
					}
				else {
					app.u.throwMessage("Jesey Previewer currently unavailable, try again later!");
					}
				}

			}, //Actions

////////////////////////////////////   RENDERFORMATS    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//renderFormats are what is used to actually output data.
//on a data-bind, format: is equal to a renderformat. extension: tells the rendering engine where to look for the renderFormat.
//that way, two render formats named the same (but in different extensions) don't overwrite each other.
		renderFormats : {
			jerseypreview : function($tag, data){
				if(data.value['%attribs'] && data.value['%attribs']['user:prod_flashparams_jersey']){
					var swfStr=	"<object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0' width='400' height='400'"
					swfStr +=	" id='jerseyPreview"+data.value.pid+"' align='middle'>"
					swfStr += 	"<param name='allowScriptAccess' value='always' />"
					swfStr += 	"<param name='allowFullScreen' value='true' />"
					swfStr += 	"<param name='movie' value='https://static---cubworld.app-hosted.com/media/merchant/cubworld/_ticket_468079/jersey_builder-400x400-20110908.swf?imagesrc=https://static---cubworld.app-hosted.com/media/img/cubworld/W400-H400-Bffffff/"
					swfStr +=	data.value['%attribs']['zoovy:prod_image8'];
					swfStr +=	"&font=http://static.zoovy.com/merchant/cubworld/_ticket_468079/"
					swfStr +=	data.value['%attribs']['user:prod_flashparams_jersey'];
					swfStr +=	"'/>"
					swfStr += 	"<param name='quality' value='high' />"
					swfStr += 	"<param name='bgcolor' value='#FFFFFF' />"
					swfStr +=	"<embed src='https://static---cubworld.app-hosted.com/media/merchant/cubworld/_ticket_468079/jersey_builder-400x400-20110908.swf?imagesrc=http://static.zoovy.com/img/cubworld/W400-H400-Bffffff/"
					swfStr +=	data.value['%attribs']['zoovy:prod_image8'];
					swfStr +=	"&font=https://static---cubworld.app-hosted.com/media/merchant/cubworld/_ticket_468079/"
					swfStr +=	data.value['%attribs']['user:prod_flashparams_jersey'];
					swfStr +=	"' quality='high' bgcolor='#FFFFFF' width='400' allowFullScreen='true' height='400' name='jerseyPreview"+data.value.pid+"' align='middle' allowScriptAccess='always' type='application/x-shockwave-flash' pluginspage='http://www.macromedia.com/go/getflashplayer' />"
					swfStr += 	"</object>"

					$tag.html(swfStr);
					$tag.attr('id','jerseyPreviewContainer'+data.value.pid);
					}
				else {
					//We are not needed here
					$tag.remove();
					}
				}
			}, //renderFormats
////////////////////////////////////   UTIL [u]   \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

//utilities are typically functions that are exected by an event or action.
//any functions that are recycled should be here.
		u : {
			thisMovie : function(movieName) {
				if (navigator.appName.indexOf("Microsoft") != -1) {
					return window[movieName];
					}
				else {
					return document[movieName];
					}
				}
			}, //u [utilities]

//app-events are added to an element through data-app-event="extensionName|functionName"
//right now, these are not fully supported, but they will be going forward.
//they're used heavily in the admin.html file.
//while no naming convention is stricly forced,
//when adding an event, be sure to do off('click.appEventName') and then on('click.appEventName') to ensure the same event is not double-added if app events were to get run again over the same template.
		e : {
			}, //e [app Events]
		vars : {
			}
		} //r object.

	return r;
	}<|endoftext|>


<commit_before>import dotenv from 'dotenv';
if (process.env.NODE_ENV !== 'production') {
    dotenv.config();
}
if (!process.env.TWITTER_CONSUMER_KEY
    || !process.env.TWITTER_CONSUMER_SECRET
    || !process.env.TWITTER_ACCESS_TOKEN_KEY
    || !process.env.TWITTER_ACCESS_TOKEN_SECRET) {
    console.error("One or more Twitter secret key environment variables have not been set.");
    process.exit(1);
}

import fs from 'fs';
import request from 'request';
import { default as time } from '../services/time';
import renderCard from './card';
import { default as twitter } from '../services/twitter';

const API_ENDPOINT = 'https://todayindestiny.herokuapp.com/api/advisors';

// note: times are in Pacific Time (accounts for Daylight Savings)
const TASKS = [
    {
        // weekly activities
        time: {
            // Tuesday, 9 AM UTC
            utc: true,
            day: 2,
            hour: 9
        },
        card: {
            template: '2x3',
            name: 'This Week',
            category: 'weekly',
            advisors: [
                'raid', 'nightfall',
                'strikes', 'story',
                'crucible'
            ],
            maxAdvisors: 6,
            getDate: () => {
                let week = time.getCurrentDestinyWeek();
                return `${week.tuesday} - ${week.monday}`;
            }
        }
    },
    {
        // Trials of Osiris
        time: {
            // Friday, 10 AM Pacific
            utc: false,
            day: 5,
            hour: 10
        },
        card: {
            template: '1x1',
            name: 'Trials of Osiris',
            category: 'events',
            advisors: ['trials'],
            maxAdvisors: 1,
            getDate: () => {
                let week = time.getCurrentDestinyWeek();
                return `${week.friday} - ${week.monday}`;
            }
        }
    }
];

// determine current time
let now = time.getCurrentTime();

// allow us to force a specific time for testing purposes
if (process.argv.length >= 4 && process.argv[2] == '--force') {
    const parsed = process.argv[3].split(':');
    now.utc = {
        day: parseInt(parsed[0]),
        hour: parseInt(parsed[1]),
        minute: parseInt(parsed[2])
    };
    now.pacific = time.toPacific(now.utc);
}

// determine which tasks are active
const cards = [];
TASKS.forEach(task => {
    if (isTaskActive(task.time, now)) {
        cards.push(task.card);
    }
}, this);

if (cards.length > 0) {
    // generate and post cards
    retry(getAdvisors, 5)
        .then(advisors => {
            let promises = cards.map(
                card => postCard(card, advisors));
            return Promise.all(promises)
        })
        .then(() => console.log('All cards posted.'))
}
else {
    console.log('No tasks active.');
}

function isTaskActive(taskTime, now) {
    const current = taskTime.utc ? now.utc : now.pacific;
    if (taskTime.day) {
        if (current.day !== taskTime.day) {
            return false;
        }
    }
    if (taskTime.hour) {
        if (current.hour !== taskTime.hour || current.minute < 5) {
            return false;
        }
    }
    return true;
}

function postCard(card, advisors) {
    let tweetText = '#Destiny';
    return generateContent(card, advisors)
        .then(content => {
            tweetText = content.tweetText || tweetText;
            return renderCard(content.card);
        })
        .then(data => tweet(tweetText, data))
        .catch(error => console.log(`Couldn't post card. (CARD: ${card.name})`));
}

function retry(promiseFunction, maxRetries) {
    return new Promise((resolve, reject) => {
        let retries = 0;

        let runTask = () => promiseFunction()
            .then(result => resolve(result))
            .catch(error => {
                console.log(error.message);

                retries++;
                if (retries > maxRetries) {
                    console.log('Failed. Max retries exceeded.');
                    reject();
                }
                else {
                    console.log(`Failed. Retrying... (${retries} / ${maxRetries})`);
                    runTask();
                }
            });

        runTask();
    });
}

function getAdvisors() {
    return new Promise((resolve, reject) => {
        console.log('Retrieving advisors...');
        request(API_ENDPOINT, (error, response, body) => {
            try {
                if (error) {
                    throw error;
                }
                let data = JSON.parse(body);
                if (response.statusCode === 200) {
                    console.log('Advisors retrieved.')
                    resolve(data.response);
                }
                else {
                    reject(new Error(data.status));
                }
            } catch (e) {
                reject(new Error('An error occurred.'));
            }
        });
    });
}

function generateContent(card, data) {
    let output = {
        template: card.template,
        cardName: card.name,
        date: card.getDate(),
        advisors: []
    };

    let category = null;
    for (let i = 0; i < data.categories.length; i++) {
        let advisorCategory = data.categories[i];
        if (advisorCategory.id === card.category) {
            category = advisorCategory;
        }
    }

    if (category) {
        for (let i = 0; i < category.advisors.length; i++) {
            if (output.advisors.length >= card.maxAdvisors) {
                break;
            }

            let advisor = category.advisors[i];
            if (card.advisors.includes(advisor.shortID)) {
                let modifiers = undefined;
                if (advisor.modifiers) {
                    modifiers = [];
                    advisor.modifiers.forEach(modifier => {
                        modifiers.push({
                            name: modifier.name,
                            icon: formatURL(modifier.icon)
                        });
                    }, this);
                }

                output.advisors.push({
                    name: advisor.name,
                    type: advisor.type,
                    image: formatURL(advisor.image),
                    icon: formatURL(advisor.icon),
                    modifiers: modifiers
                });
            }
        }
    }

    return Promise.resolve({
        card: output,
        tweetText: `${output.cardName} in #Destiny (${output.date})`
    });
}

function formatURL(url) {
    if (url.startsWith('http')) {
        return url;
    }
    else {
        return `build/public${url}`;
    }
}

function tweet(text, media) {
    return twitter.tweet(text, media)
        .then(() => console.log(`Tweet posted. (Tweet: ${text})`));
}<commit_msg>Remove Trials card.<commit_after>import dotenv from 'dotenv';
if (process.env.NODE_ENV !== 'production') {
    dotenv.config();
}
if (!process.env.TWITTER_CONSUMER_KEY
    || !process.env.TWITTER_CONSUMER_SECRET
    || !process.env.TWITTER_ACCESS_TOKEN_KEY
    || !process.env.TWITTER_ACCESS_TOKEN_SECRET) {
    console.error("One or more Twitter secret key environment variables have not been set.");
    process.exit(1);
}

import fs from 'fs';
import request from 'request';
import { default as time } from '../services/time';
import renderCard from './card';
import { default as twitter } from '../services/twitter';

const API_ENDPOINT = 'https://todayindestiny.herokuapp.com/api/advisors';

// note: times are in Pacific Time (accounts for Daylight Savings)
const TASKS = [
    {
        // weekly activities
        time: {
            // Tuesday, 9 AM UTC
            utc: true,
            day: 2,
            hour: 9
        },
        card: {
            template: '2x3',
            name: 'This Week',
            category: 'weekly',
            advisors: [
                'raid', 'nightfall',
                'strikes', 'story',
                'crucible'
            ],
            maxAdvisors: 6,
            getDate: () => {
                let week = time.getCurrentDestinyWeek();
                return `${week.tuesday} - ${week.monday}`;
            }
        }
    }
];

// determine current time
let now = time.getCurrentTime();

// allow us to force a specific time for testing purposes
if (process.argv.length >= 4 && process.argv[2] == '--force') {
    const parsed = process.argv[3].split(':');
    now.utc = {
        day: parseInt(parsed[0]),
        hour: parseInt(parsed[1]),
        minute: parseInt(parsed[2])
    };
    now.pacific = time.toPacific(now.utc);
}

// determine which tasks are active
const cards = [];
TASKS.forEach(task => {
    if (isTaskActive(task.time, now)) {
        cards.push(task.card);
    }
}, this);

if (cards.length > 0) {
    // generate and post cards
    retry(getAdvisors, 5)
        .then(advisors => {
            let promises = cards.map(
                card => postCard(card, advisors));
            return Promise.all(promises)
        })
        .then(() => console.log('All cards posted.'))
}
else {
    console.log('No tasks active.');
}

function isTaskActive(taskTime, now) {
    const current = taskTime.utc ? now.utc : now.pacific;
    if (taskTime.day) {
        if (current.day !== taskTime.day) {
            return false;
        }
    }
    if (taskTime.hour) {
        if (current.hour !== taskTime.hour || current.minute < 5) {
            return false;
        }
    }
    return true;
}

function postCard(card, advisors) {
    let tweetText = '#Destiny';
    return generateContent(card, advisors)
        .then(content => {
            tweetText = content.tweetText || tweetText;
            return renderCard(content.card);
        })
        .then(data => tweet(tweetText, data))
        .catch(error => console.log(`Couldn't post card. (CARD: ${card.name})`));
}

function retry(promiseFunction, maxRetries) {
    return new Promise((resolve, reject) => {
        let retries = 0;

        let runTask = () => promiseFunction()
            .then(result => resolve(result))
            .catch(error => {
                console.log(error.message);

                retries++;
                if (retries > maxRetries) {
                    console.log('Failed. Max retries exceeded.');
                    reject();
                }
                else {
                    console.log(`Failed. Retrying... (${retries} / ${maxRetries})`);
                    runTask();
                }
            });

        runTask();
    });
}

function getAdvisors() {
    return new Promise((resolve, reject) => {
        console.log('Retrieving advisors...');
        request(API_ENDPOINT, (error, response, body) => {
            try {
                if (error) {
                    throw error;
                }
                let data = JSON.parse(body);
                if (response.statusCode === 200) {
                    console.log('Advisors retrieved.')
                    resolve(data.response);
                }
                else {
                    reject(new Error(data.status));
                }
            } catch (e) {
                reject(new Error('An error occurred.'));
            }
        });
    });
}

function generateContent(card, data) {
    let output = {
        template: card.template,
        cardName: card.name,
        date: card.getDate(),
        advisors: []
    };

    let category = null;
    for (let i = 0; i < data.categories.length; i++) {
        let advisorCategory = data.categories[i];
        if (advisorCategory.id === card.category) {
            category = advisorCategory;
        }
    }

    if (category) {
        for (let i = 0; i < category.advisors.length; i++) {
            if (output.advisors.length >= card.maxAdvisors) {
                break;
            }

            let advisor = category.advisors[i];
            if (card.advisors.includes(advisor.shortID)) {
                let modifiers = undefined;
                if (advisor.modifiers) {
                    modifiers = [];
                    advisor.modifiers.forEach(modifier => {
                        modifiers.push({
                            name: modifier.name,
                            icon: formatURL(modifier.icon)
                        });
                    }, this);
                }

                output.advisors.push({
                    name: advisor.name,
                    type: advisor.type,
                    image: formatURL(advisor.image),
                    icon: formatURL(advisor.icon),
                    modifiers: modifiers
                });
            }
        }
    }

    return Promise.resolve({
        card: output,
        tweetText: `${output.cardName} in #Destiny (${output.date})`
    });
}

function formatURL(url) {
    if (url.startsWith('http')) {
        return url;
    }
    else {
        return `build/public${url}`;
    }
}

function tweet(text, media) {
    return twitter.tweet(text, media)
        .then(() => console.log(`Tweet posted. (Tweet: ${text})`));
}<|endoftext|>


<commit_before>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

/*eslint strict:["error", "global"]*/
'use strict';

const _path = require('path');
const _fs = require('fs-extra');

const _utils = require('./utils.js');

const ROOT = _path.dirname(_path.dirname(_path.join(__dirname)));

///////////////////////////////////////////////////////////////////////////////
// HELPERS
///////////////////////////////////////////////////////////////////////////////

/*
 * Reads given config template and replaces any required strings
 */
function _createWebserverConfig(cfg, target, src, mimecb) {
  const mimes = mimecb(cfg.mime);

  var tpl = _fs.readFileSync(src).toString();
  tpl = tpl.replace(/%DISTDIR%/, _path.join(ROOT, target));
  tpl = tpl.replace(/%MIMES%/, mimes);
  return tpl;
}

/*
 * Reads given template file and replaces example strings
 */
function _replaceInExample(name, file, dest) {
  dest = dest ? dest : file;

  var c = _fs.readFileSync(file).toString();
  c = _utils.replaceAll(c, 'EXAMPLE', name);
  _fs.writeFileSync(dest, c);
}

///////////////////////////////////////////////////////////////////////////////
// TASKS
///////////////////////////////////////////////////////////////////////////////

const TASKS = {
  'apache_vhost': function(cli, cfg) {
    const src = _path.join(ROOT, 'src', 'templates', 'apache', 'vhost.conf');
    const target = cli.option('target', 'dist');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return '';
    }));
  },

  'apache_htaccess': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const mimes = [];
    const proxies = [];

    Object.keys(cfg.mime.mapping).forEach((i) => {
      if ( i.match(/^\./) ) {
        mimes.push('  AddType ' + cfg.mime.mapping[i] + ' ' + i);
      }
    });

    Object.keys(cfg.server.proxies).forEach((k) => {
      if ( k.substr(0, 1) !== '/' && typeof cfg.server.proxies[k] === 'string' ) {
        proxies.push('     RewriteRule ' + k + ' ' + cfg.server.proxies[k] + ' [P]');
      }
    });

    function generate_htaccess(t, d) {
      const src = _path.join(ROOT, 'src', 'templates', t);
      const dst = _path.join(ROOT, d, '.htaccess');

      var tpl = _fs.readFileSync(src).toString();
      tpl = tpl.replace(/%MIMES%/, mimes.join('\n'));
      tpl = tpl.replace(/%PROXIES%/, proxies.join('\n'));
      _fs.writeFileSync(dst, tpl);
    }

    if ( target === 'dist' ) {
      generate_htaccess('apache/prod-htaccess.conf', target);
    } else {
      generate_htaccess('apache/prod-htaccess.conf', 'dist');
      generate_htaccess('apache/dev-htaccess.conf', 'dist-dev');
    }

    return Promise.resolve();
  },

  'lighttpd_config': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const src = _path.join(ROOT, 'src', 'templates', 'lighttpd.conf');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return Object.keys(mime.mapping).map((i) => {
        return i.match(/^\./) ? '  "' + i + '" => "' + mime.mapping[i] + '"' : null;
      }).filter((i) => {
        return !!i;
      }).join(',\n');
    }));
  },

  'nginx_config': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const src = _path.join(ROOT, 'src', 'templates', 'nginx.conf');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return Object.keys(mime.mapping).map((i) => {
        return i.match(/^\./) ? ('        ' + mime.mapping[i] + ' ' + i.replace(/^\./, '') + ';') : null;
      }).filter((i) => {
        return !!i;
      }).join('\n');
    }));
  },

  'package': function(cli, cfg) {
    const type = cli.option('type', 'application');

    var name = cli.option('name', '');

    const tmp  = name.split('/');
    const repo = tmp.length > 1 ? tmp[0] : 'default';
    name = tmp.length > 1 ? tmp[1] : name;

    const typemap = {
      iframe: {
        src: 'iframe-application',
        cpy: ['main.js', 'metadata.json']
      },
      dummy: {
        src: 'dummy',
        cpy: ['main.js', 'metadata.json']
      },
      application: {
        src: 'application',
        cpy: ['api.js', 'main.js', 'main.css', 'metadata.json', 'scheme.html']
      },
      simple: {
        src: 'simple-application',
        cpy: ['api.js', 'main.js', 'main.css', 'metadata.json', 'scheme.html']
      },
      service: {
        src: 'service',
        cpy: ['api.js', 'main.js', 'metadata.json']
      },
      extension: {
        src: 'extension',
        cpy: ['api.js', 'extension.js', 'metadata.json']
      }
    };

    if ( !name ) {
      throw new Error('You have to specify a name');
    }

    const src = _path.join(ROOT, 'src', 'templates', 'package', typemap[type].src);
    const dst = _path.join(ROOT, 'src', 'packages', repo, name);

    if ( !_fs.existsSync(src) ) {
      throw new Error('Template not found');
    }

    if ( _fs.existsSync(dst) ) {
      throw new Error('Package already exists');
    }

    _fs.copySync(src, dst);

    typemap[type].cpy.forEach((c) => {
      _replaceInExample(name, _path.join(dst, c), false);
    });

    if ( (cfg.repositories || []).indexOf(repo) < 0 ) {
      console.warn(String.color('The repository \'' + repo + '\' is not active.', 'yellow'));
    }

    return Promise.resolve();
  }

};

///////////////////////////////////////////////////////////////////////////////
// EXPORTS
///////////////////////////////////////////////////////////////////////////////

module.exports = TASKS;
<commit_msg>build: Normalize package name input for generator<commit_after>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2017, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */

/*eslint strict:["error", "global"]*/
'use strict';

const _path = require('path');
const _fs = require('fs-extra');

const _utils = require('./utils.js');

const ROOT = _path.dirname(_path.dirname(_path.join(__dirname)));

///////////////////////////////////////////////////////////////////////////////
// HELPERS
///////////////////////////////////////////////////////////////////////////////

/*
 * Reads given config template and replaces any required strings
 */
function _createWebserverConfig(cfg, target, src, mimecb) {
  const mimes = mimecb(cfg.mime);

  var tpl = _fs.readFileSync(src).toString();
  tpl = tpl.replace(/%DISTDIR%/, _path.join(ROOT, target));
  tpl = tpl.replace(/%MIMES%/, mimes);
  return tpl;
}

/*
 * Reads given template file and replaces example strings
 */
function _replaceInExample(name, file, dest) {
  dest = dest ? dest : file;

  var c = _fs.readFileSync(file).toString();
  c = _utils.replaceAll(c, 'EXAMPLE', name);
  _fs.writeFileSync(dest, c);
}

///////////////////////////////////////////////////////////////////////////////
// TASKS
///////////////////////////////////////////////////////////////////////////////

const TASKS = {
  'apache_vhost': function(cli, cfg) {
    const src = _path.join(ROOT, 'src', 'templates', 'apache', 'vhost.conf');
    const target = cli.option('target', 'dist');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return '';
    }));
  },

  'apache_htaccess': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const mimes = [];
    const proxies = [];

    Object.keys(cfg.mime.mapping).forEach((i) => {
      if ( i.match(/^\./) ) {
        mimes.push('  AddType ' + cfg.mime.mapping[i] + ' ' + i);
      }
    });

    Object.keys(cfg.server.proxies).forEach((k) => {
      if ( k.substr(0, 1) !== '/' && typeof cfg.server.proxies[k] === 'string' ) {
        proxies.push('     RewriteRule ' + k + ' ' + cfg.server.proxies[k] + ' [P]');
      }
    });

    function generate_htaccess(t, d) {
      const src = _path.join(ROOT, 'src', 'templates', t);
      const dst = _path.join(ROOT, d, '.htaccess');

      var tpl = _fs.readFileSync(src).toString();
      tpl = tpl.replace(/%MIMES%/, mimes.join('\n'));
      tpl = tpl.replace(/%PROXIES%/, proxies.join('\n'));
      _fs.writeFileSync(dst, tpl);
    }

    if ( target === 'dist' ) {
      generate_htaccess('apache/prod-htaccess.conf', target);
    } else {
      generate_htaccess('apache/prod-htaccess.conf', 'dist');
      generate_htaccess('apache/dev-htaccess.conf', 'dist-dev');
    }

    return Promise.resolve();
  },

  'lighttpd_config': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const src = _path.join(ROOT, 'src', 'templates', 'lighttpd.conf');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return Object.keys(mime.mapping).map((i) => {
        return i.match(/^\./) ? '  "' + i + '" => "' + mime.mapping[i] + '"' : null;
      }).filter((i) => {
        return !!i;
      }).join(',\n');
    }));
  },

  'nginx_config': function(cli, cfg) {
    const target = cli.option('target', 'dist');

    const src = _path.join(ROOT, 'src', 'templates', 'nginx.conf');

    return Promise.resolve(_createWebserverConfig(cfg, target, src, function(mime) {
      return Object.keys(mime.mapping).map((i) => {
        return i.match(/^\./) ? ('        ' + mime.mapping[i] + ' ' + i.replace(/^\./, '') + ';') : null;
      }).filter((i) => {
        return !!i;
      }).join('\n');
    }));
  },

  'package': function(cli, cfg) {
    var name = cli.option('name', '');
    const type = cli.option('type', 'application');
    const words = name.replace(/\s+/g, ' ').split(' ');
    name = [words[0]].concat(words.splice(1).map((w) => {
      return w.replace(/\b\w/g, (l) => l.toUpperCase());
    })).join('');

    const tmp  = name.split('/');
    const repo = tmp.length > 1 ? tmp[0] : 'default';
    name = tmp.length > 1 ? tmp[1] : name;

    const typemap = {
      iframe: {
        src: 'iframe-application',
        cpy: ['main.js', 'metadata.json']
      },
      dummy: {
        src: 'dummy',
        cpy: ['main.js', 'metadata.json']
      },
      application: {
        src: 'application',
        cpy: ['api.js', 'main.js', 'main.css', 'metadata.json', 'scheme.html']
      },
      simple: {
        src: 'simple-application',
        cpy: ['api.js', 'main.js', 'main.css', 'metadata.json', 'scheme.html']
      },
      service: {
        src: 'service',
        cpy: ['api.js', 'main.js', 'metadata.json']
      },
      extension: {
        src: 'extension',
        cpy: ['api.js', 'extension.js', 'metadata.json']
      }
    };

    if ( !name ) {
      throw new Error('You have to specify a name');
    }

    const src = _path.join(ROOT, 'src', 'templates', 'package', typemap[type].src);
    const dst = _path.join(ROOT, 'src', 'packages', repo, name);

    if ( !_fs.existsSync(src) ) {
      throw new Error('Template not found');
    }

    if ( _fs.existsSync(dst) ) {
      throw new Error('Package already exists');
    }

    _fs.copySync(src, dst);

    typemap[type].cpy.forEach((c) => {
      _replaceInExample(name, _path.join(dst, c), false);
    });

    if ( (cfg.repositories || []).indexOf(repo) < 0 ) {
      console.warn(String.color('The repository \'' + repo + '\' is not active.', 'yellow'));
    }

    return Promise.resolve();
  }

};

///////////////////////////////////////////////////////////////////////////////
// EXPORTS
///////////////////////////////////////////////////////////////////////////////

module.exports = TASKS;
<|endoftext|>


<commit_before>var gulp = require('gulp'),
    //debug = require('gulp-debug'),
    merge = require('merge-stream'),
    flatten = require('gulp-flatten'),
    shell = require('gulp-shell'),
    del = require('del'),
    assemblyInfo = require('gulp-dotnet-assembly-info'),
    argv = require('yargs').argv,
    sequence = require('run-sequence');

var ver = '0.3.0',
    config = {
        srcdir: './../',
        projects: ['Routemeister'],
        build: {
            outdir: './artifacts/',
            semver: ver, //suffix e.g. 'rc-1'
            version: ver + '.' + (argv && argv.buildrevision ? argv.buildrevision : '0'),
            profile: argv && argv.buildprofile ? argv.buildprofile : 'Release'
        },
        tools: {
            msbuild: '"C:/Program Files (x86)/MSBuild/14.0/Bin/MSBuild.exe"',
            nunit: '"./tools/NUnit.ConsoleRunner.3.2.0/tools/nunit3-console.exe"'
        }
    };

gulp.task('default', function (cb) {
    sequence(
        ['clean','assemblyinfo'],
        'build',
        'unit-tests',
        'copy',
        cb);
});

gulp.task('ci', function (cb) {
    sequence(
        ['init-tools', 'clean', 'assemblyinfo', 'nuget-restore'],
        'build',
        'unit-tests',
        'copy',
        'nuget-pack',
        cb);
});

gulp.task('init-tools', shell.task('nuget restore ./tools/packages.config -o ./tools/'));

gulp.task('nuget-restore', function () {
    return gulp.src(config.srcdir + '*.sln', { read: false })
        .pipe(shell('nuget restore <%= file.path %>'));
});

gulp.task('clean', function(cb) {
    return del(config.build.outdir);
});

gulp.task('assemblyinfo', function() {
    return gulp.src(config.srcdir + 'GlobalAssemblyInfo.cs')
        .pipe(assemblyInfo({
          version: config.build.version,
          informationalVersion: config.build.semver
        }))
        .pipe(gulp.dest(config.srcdir));
});

gulp.task('build', function() {
    return gulp.src(config.srcdir + '*.sln', { read: false })
        .pipe(shell(config.tools.msbuild + ' <%= file.path %> /v:quiet /t:Clean /t:Rebuild /p:Configuration=' + config.build.profile));
});

gulp.task('copy', function() {
    var tasks = config.projects.map(function (name) {
        return gulp.src(config.srcdir + name + '/bin/' + config.build.profile + '/*.{dll,XML}')
            .pipe(flatten())
            .pipe(gulp.dest(config.build.outdir + '/' + name));
    });

    return merge(tasks);
});

gulp.task('unit-tests', function () {
    return gulp.src(config.srcdir + '*.UnitTests/**/bin/' + config.build.profile + '/*.UnitTests.dll')
        .pipe(shell(config.tools.nunit + ' <%= file.path %> --noresult'));
});

gulp.task('nuget-pack', function () {
    return gulp.src('*.nuspec', { read: false })
        .pipe(shell('nuget pack <%= file.path %> -version ' + config.build.semver + ' -basepath ' + config.build.outdir + ' -o ' + config.build.outdir));
});
<commit_msg>Bumped to v1.0.0<commit_after>var gulp = require('gulp'),
    //debug = require('gulp-debug'),
    merge = require('merge-stream'),
    flatten = require('gulp-flatten'),
    shell = require('gulp-shell'),
    del = require('del'),
    assemblyInfo = require('gulp-dotnet-assembly-info'),
    argv = require('yargs').argv,
    sequence = require('run-sequence');

var ver = '1.0.0',
    config = {
        srcdir: './../',
        projects: ['Routemeister'],
        build: {
            outdir: './artifacts/',
            semver: ver, //suffix e.g. 'rc-1'
            version: ver + '.' + (argv && argv.buildrevision ? argv.buildrevision : '0'),
            profile: argv && argv.buildprofile ? argv.buildprofile : 'Release'
        },
        tools: {
            msbuild: '"C:/Program Files (x86)/MSBuild/14.0/Bin/MSBuild.exe"',
            nunit: '"./tools/NUnit.ConsoleRunner.3.2.0/tools/nunit3-console.exe"'
        }
    };

gulp.task('default', function (cb) {
    sequence(
        ['clean','assemblyinfo'],
        'build',
        'unit-tests',
        'copy',
        cb);
});

gulp.task('ci', function (cb) {
    sequence(
        ['init-tools', 'clean', 'assemblyinfo', 'nuget-restore'],
        'build',
        'unit-tests',
        'copy',
        'nuget-pack',
        cb);
});

gulp.task('init-tools', shell.task('nuget restore ./tools/packages.config -o ./tools/'));

gulp.task('nuget-restore', function () {
    return gulp.src(config.srcdir + '*.sln', { read: false })
        .pipe(shell('nuget restore <%= file.path %>'));
});

gulp.task('clean', function(cb) {
    return del(config.build.outdir);
});

gulp.task('assemblyinfo', function() {
    return gulp.src(config.srcdir + 'GlobalAssemblyInfo.cs')
        .pipe(assemblyInfo({
          version: config.build.version,
          informationalVersion: config.build.semver
        }))
        .pipe(gulp.dest(config.srcdir));
});

gulp.task('build', function() {
    return gulp.src(config.srcdir + '*.sln', { read: false })
        .pipe(shell(config.tools.msbuild + ' <%= file.path %> /v:quiet /t:Clean /t:Rebuild /p:Configuration=' + config.build.profile));
});

gulp.task('copy', function() {
    var tasks = config.projects.map(function (name) {
        return gulp.src(config.srcdir + name + '/bin/' + config.build.profile + '/*.{dll,XML}')
            .pipe(flatten())
            .pipe(gulp.dest(config.build.outdir + '/' + name));
    });

    return merge(tasks);
});

gulp.task('unit-tests', function () {
    return gulp.src(config.srcdir + '*.UnitTests/**/bin/' + config.build.profile + '/*.UnitTests.dll')
        .pipe(shell(config.tools.nunit + ' <%= file.path %> --noresult'));
});

gulp.task('nuget-pack', function () {
    return gulp.src('*.nuspec', { read: false })
        .pipe(shell('nuget pack <%= file.path %> -version ' + config.build.semver + ' -basepath ' + config.build.outdir + ' -o ' + config.build.outdir));
});
<|endoftext|>


<commit_before>define(function(require, exports, module) {
  "use strict";

  var fn = require("./fn");
  var array = require("./array");
  var slice = [].slice;

  var UGen = (function() {
    function UGen() {
      this.audio  = "audio";
      this.inputs = [];
    }

    UGen.prototype.$new1 = function(rate) {
      var args = slice.call(arguments, 1);
      this.rate = rate;
      return this.initialize.apply(this, args);
    };
    UGen.prototype.$multiNew = function() {
      return this.multiNewList(slice.call(arguments));
    };
    UGen.prototype.$multiNewList = function(list) {
      var zipped = array.zip.apply(null, list);
      if (zipped.length === 1) {
        return this.new1.apply(this, list);
      }
      return zipped.map(function(list) {
        return this.constructor.multiNewList(list);
      }, this);
    };
    fn.classmethod(UGen);

    UGen.prototype.initialize = function() {
      this.inputs = slice.call(arguments);
      return this;
    };

    return UGen;
  })();

  module.exports = {
    UGen: UGen
  };

});
<commit_msg>Fixed default rate of UGen<commit_after>define(function(require, exports, module) {
  "use strict";

  var fn = require("./fn");
  var array = require("./array");
  var slice = [].slice;

  var UGen = (function() {
    function UGen() {
      this.rate   = "AUDIO";
      this.inputs = [];
    }

    UGen.prototype.$new1 = function(rate) {
      var args = slice.call(arguments, 1);
      this.rate = rate;
      return this.initialize.apply(this, args);
    };
    UGen.prototype.$multiNew = function() {
      return this.multiNewList(slice.call(arguments));
    };
    UGen.prototype.$multiNewList = function(list) {
      var zipped = array.zip.apply(null, list);
      if (zipped.length === 1) {
        return this.new1.apply(this, list);
      }
      return zipped.map(function(list) {
        return this.constructor.multiNewList(list);
      }, this);
    };
    fn.classmethod(UGen);

    UGen.prototype.initialize = function() {
      this.inputs = slice.call(arguments);
      return this;
    };

    return UGen;
  })();

  module.exports = {
    UGen: UGen
  };

});
<|endoftext|>


<commit_before>function CharacterPage(utils) {
  this.utils = utils;
  this.name_column = null;
  this.vocation_column = null;
  this.level_column = null;
  this.world_column = null;
  this.married_column = null;
  this.must_be_online = false; // Will be set if online is displayed on the page

  // These fields will be set if the columns are valid.
  this.name = null;
  this.vocation = null;
  this.level = null;
  this.world = null;
  this.married = null;
}

/**
 * Retrieves and stores information from the character information table.
 * @return False if something is missing.
 */
CharacterPage.prototype.parseCharacterInformation = function(callback) {
  var self = this;
  var character_information_rows = $('table:contains("Character Information") tr');

  var name_column = character_information_rows.filter(':contains("Name:")').find('td').eq(1);
  var vocation_column = character_information_rows.filter(':contains("Vocation:")').find('td').eq(1);
  var level_column = character_information_rows.filter(':contains("Level:")').find('td').eq(1);
  var world_column = character_information_rows.filter(':contains("World:")').find('td').eq(1);
  var married_column = character_information_rows.filter(':contains("Married to:")').find('td').eq(1);

  if (name_column.size() === 1) {
    self.name_column = name_column;
    self.name = name_column.text().trim();
  } else {
    return callback('Name not found');
  }

  if (vocation_column.size() === 1) {
    self.vocation_column = vocation_column;
    self.vocation = vocation_column.text().trim();
  } else {
    return callback('Vocation not found');
  }

  if (level_column.size() === 1) {
    self.level_column = level_column;
    self.level = parseInt(level_column.text().trim(), 10);
  } else {
    return callback('Level not found');
  }

  if (world_column.size() === 1) {
    self.world_column = world_column;
    self.world = world_column.text().trim();
  } else {
    return callback('World not found');
  }

  if (married_column.size() === 1) {
    self.married_column = married_column;
    self.married = married_column.text().trim();
  }

  return callback(null);
};

/**
 * Checks if character is online by looking at characters (possible if not a hidden character)
 */
CharacterPage.prototype.parseCharacters = function() {
  var self = this;
  var safe_name = self.utils.to_property_name(self.name);
  var characters_rows = $('table:contains("Characters") tr').slice(2).has('nobr'); // Remove header

  characters_rows.each(function() {
    var tmp_name = self.utils.to_property_name(($(this).find('td').eq(0).text().split('.')[1] + '').trim());
    if (tmp_name === safe_name) {
      // Its our character!
      self.must_be_online = $(this).find('td').eq(2).text().trim() === 'online';
      return false;
    }
  });
};

/**
 * Updates the character information
 */
CharacterPage.prototype.updateCharacterInformation = function(players, callback) {
  var self = this;
  var safe_name = self.utils.to_property_name(self.name);
  var player = players[safe_name];
  if (player) {
    // Character is online
    self.name_column.html('' + self.name + '');

    // Set level
    var level_diff = player.level - self.level;
    if (level_diff < 0) {
      // Lost level
      self.level_column.html(player.level + ' (' + (level_diff) + ')');
    } else if (level_diff > 0) {
      // Gained level
      self.level_column.html(player.level + ' (+' + (level_diff) + ')');
    }

    // Set vocation
    self.vocation_column.text(player.vocation);
  } else if (self.must_be_online) {
    // Character is online but not in the list
    self.name_column.html('' + self.name + '');
  }

  if (self.married_column) {
    var married_safe_name = self.utils.to_property_name(self.married);
    var married_player = players[married_safe_name];
    if (married_player) {
      // Married character is online
      self.married_column.find('a').addClass('green');
    }
  }
  return callback(null);
};

/**
 * Mark all killers if they are online
 */
CharacterPage.prototype.updateCharacterDeaths = function(players) {
  var character_deaths_rows = $('table:contains("Character Deaths") tr').slice(1);
  if (character_deaths_rows.size() > 0) {
    character_deaths_rows.each(function() {
      $(this).find('td a').each(function() {
        var tmp_name = self.utils.to_property_name($(this).text());
        var killer = players[tmp_name];
        if (killer) {
          // Killer character is online
          $(this).addClass('green');
        }
      });
    });
  }
};

exports.CharacterPage = CharacterPage;
<commit_msg>Started to transform from jquery to dom<commit_after>function CharacterPage(utils) {
  this.utils = utils;
  this.name_column = null;
  this.vocation_column = null;
  this.level_column = null;
  this.married_column = null;
  this.must_be_online = false; // Will be set if online is displayed on the page

  // These fields will be set if parseCharacterInformation return ok
  this.name = null;
  this.vocation = null;
  this.level = null;
  this.world = null;
  this.married = null;
}

/**
 * Retrieves and stores information from the character information table.
 * @return False if something is missing.
 */
CharacterPage.prototype.parseCharacterInformation = function(callback) {
  var self = this;
  var character_information_rows = $('table:contains("Character Information") tr');

  var name_column = character_information_rows.filter(':contains("Name:")').find('td').eq(1);
  var vocation_column = character_information_rows.filter(':contains("Vocation:")').find('td').eq(1);
  var level_column = character_information_rows.filter(':contains("Level:")').find('td').eq(1);
  var world_column = character_information_rows.filter(':contains("World:")').find('td').eq(1);
  var married_column = character_information_rows.filter(':contains("Married to:")').find('td').eq(1);

  if (name_column.size() === 1) {
    self.name_column = name_column.get(0);
    self.name = name_column.text().trim();
  } else {
    return callback('Name not found');
  }

  if (vocation_column.size() === 1) {
    self.vocation_column = vocation_column.get(0);
    self.vocation = vocation_column.text().trim();
  } else {
    return callback('Vocation not found');
  }

  if (level_column.size() === 1) {
    self.level_column = level_column.get(0);
    self.level = parseInt(level_column.text().trim(), 10);
  } else {
    return callback('Level not found');
  }

  if (world_column.size() === 1) {
    self.world = world_column.text().trim();
  } else {
    return callback('World not found');
  }

  if (married_column.size() === 1) {
    self.married_column = married_column.find('a').get(0);
    self.married = married_column.text().trim();
  }

  return callback(null);
};

/**
 * Checks if character is online by looking at characters (possible if not a hidden character)
 */
CharacterPage.prototype.parseCharacters = function() {
  var self = this;
  var safe_name = self.utils.to_property_name(self.name);
  var characters_rows = $('table:contains("Characters") tr').slice(2).has('nobr'); // Remove header

  characters_rows.each(function() {
    var tmp_name = self.utils.to_property_name(($(this).find('td').eq(0).text().split('.')[1] + '').trim());
    if (tmp_name === safe_name) {
      // Its our character!
      self.must_be_online = $(this).find('td').eq(2).text().trim() === 'online';
      return false;
    }
  });
};

/**
 * Updates the character information
 */
CharacterPage.prototype.updateCharacterInformation = function(players, callback) {
  var self = this;
  var safe_name = self.utils.to_property_name(self.name);
  var player = players[safe_name];
  if (player) {
    // Character is online
    self.name_column.innerHTML = '' + self.name + '';

    // Set level
    var level_diff = player.level - self.level;
    if (level_diff < 0) {
      // Lost level
      self.level_column.innerHTML = player.level + ' (' + (level_diff) + ')';
    } else if (level_diff > 0) {
      // Gained level
      self.level_column.innerHTML = player.level + ' (+' + (level_diff) + ')';
    }

    // Set vocation
    self.vocation_column.innerHTML = player.vocation;
  } else if (self.must_be_online) {
    // Character is online but not in the list
    self.name_column.innerHTML = '' + self.name + '';
  }

  if (self.married_column) {
    var married_safe_name = self.utils.to_property_name(self.married);
    var married_player = players[married_safe_name];
    if (married_player) {
      // Married character is online
      self.married_column.classList.add('green');
    }
  }
  return callback(null);
};

/**
 * Mark all killers if they are online
 */
CharacterPage.prototype.updateCharacterDeaths = function(players) {
  var character_deaths_rows = $('table:contains("Character Deaths") tr').slice(1);
  if (character_deaths_rows.size() > 0) {
    character_deaths_rows.each(function() {
      $(this).find('td a').each(function() {
        var tmp_name = self.utils.to_property_name($(this).text());
        var killer = players[tmp_name];
        if (killer) {
          // Killer character is online
          $(this).addClass('green');
        }
      });
    });
  }
};

exports.CharacterPage = CharacterPage;
<|endoftext|>