<commit_before>'use strict'

let log = require("./logger.js")(__filename, "info");

let fs = require('fs');
let f = require('./Firewalla.js');

const redis = require('redis')
const rclient = require('../util/redis_manager.js').getRedisClient()
const sclient = require('../util/redis_manager.js').getSubscriptionClient()
const pclient = require('../util/redis_manager.js').getPublishClient()

const async = require('asyncawait/async')
const await = require('asyncawait/await')

const dynamicConfigKey = "sys:features"

var dynamicConfigs = {}

let callbacks = {}

let config = null;

function getConfig() {
  if(!config) {
    let defaultConfig = JSON.parse(fs.readFileSync(f.getFirewallaHome() + "/net2/config.json", 'utf8'));
    let userConfigFile = f.getUserConfigFolder() + "/config.json";
    let userConfig = {};
    if(fs.existsSync(userConfigFile)) {
      userConfig = JSON.parse(fs.readFileSync(userConfigFile, 'utf8'));
    }

    let testConfig = {};
    if(process.env.NODE_ENV === 'test') {
      let testConfigFile = f.getUserConfigFolder() + "/config.test.json";
      if(fs.existsSync(testConfigFile)) {
        testConfig = JSON.parse(fs.readFileSync(testConfigFile, 'utf8'));
        log.warn("Test config is being used", testConfig, {});
      }
    }

    // user config will override system default config file
    config = Object.assign({}, defaultConfig, userConfig, testConfig);
  }
  return config;
}

function isFeatureOn_Static(featureName) {
  let config = getConfig()
  if(config.userFeatures && featureName in config.userFeatures) {
    if(config.userFeatures[featureName]) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

// undefined: feature not exists
// true: feature enabled
// false: feature disabled
function isFeatureOn_Dynamic(featureName) {
  if(dynamicConfigs && featureName in dynamicConfigs) {
    if(dynamicConfigs[featureName] === '1' ) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

function isFeatureOn(featureName) {
  const dynamicFlag = isFeatureOn_Dynamic(featureName)
  if(dynamicFlag !== undefined) {
    return dynamicFlag
  }

  const staticFlag = isFeatureOn_Static(featureName)
  if(staticFlag !== undefined) {
    return staticFlag
  } else {
    return false // default disabled
  }
}

function syncDynamicFeaturesConfigs() {
  return async(() => {
    let configs = await (rclient.hgetallAsync(dynamicConfigKey))
    if(configs) {
      dynamicConfigs = configs
    } else {
      dynamicConfigs = {}
    }
  })()
}

function enableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '1'))
    pclient.publish("config:feature:dynamic:enable", featureName)
    dynamicConfigs[featureName] = '1'
  })()
}

function disableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '0'))
    pclient.publish("config:feature:dynamic:disable", featureName)
    dynamicConfigs[featureName] = '0'
  })()
}

function clearDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hdel(dynamicConfigKey, featureName))
    pclient.publish("config:feature:dynamic:clear", featureName)
    delete dynamicConfigs[featureName]
  })()
}

function getDynamicConfigs() {
  return dynamicConfigs
}

function getFeatures() {
  let staticFeatures = getConfig().userFeatures
  let dynamicFeatures = getDynamicConfigs()

  let x = {}

  let merged = Object.assign(x, staticFeatures, dynamicFeatures)

  for(let key in merged) {
    if(merged[key] == '0') {
      merged[key] = false
    }

    if(merged[key] == '1') {
      merged[key] = true
    }
  }

  const hiddenFeatures = getConfig().hiddenFeatures;

  if(hiddenFeatures && Array.isArray(hiddenFeatures)) {
    merged = merged.filter((x) => {
      return !hiddenFeatures.includes(x); // should be filtered out if hiddenFeatures contain the feature, this can force this feature not seen from app side
    })
  }

  return merged
}

sclient.subscribe("config:feature:dynamic:enable")
sclient.subscribe("config:feature:dynamic:disable")
sclient.subscribe("config:feature:dynamic:clear")

sclient.on("message", (channel, message) => {
  log.info(`got message from ${channel}: ${message}`)
  const theFeature = message
  switch(channel) {
  case "config:feature:dynamic:enable":
    dynamicConfigs[theFeature] = '1'
    if(callbacks[theFeature]) {
      callbacks[theFeature].forEach((c) => {
        c(theFeature, true)
      })
    }
    break
  case "config:feature:dynamic:disable":
    dynamicConfigs[theFeature] = '0'
    if(callbacks[theFeature]) {
      callbacks[theFeature].forEach((c) => {
        c(theFeature, false)
      })
    }
    break
  case "config:feature:dynamic:clear":
    delete dynamicConfigs[theFeature]
    break
  }
});

syncDynamicFeaturesConfigs()

setInterval(() => {
  syncDynamicFeaturesConfigs()
}, 60 * 1000) // every minute

function onFeature(feature, callback) {
  if(!callbacks[feature]) {
    callbacks[feature] = []
  }

  callbacks[feature].push(callback)
}

module.exports = {
  getConfig: getConfig,
  isFeatureOn: isFeatureOn,
  getFeatures: getFeatures,
  getDynamicConfigs: getDynamicConfigs,
  enableDynamicFeature:enableDynamicFeature,
  disableDynamicFeature:disableDynamicFeature,
  clearDynamicFeature: clearDynamicFeature,
  syncDynamicFeaturesConfigs: syncDynamicFeaturesConfigs,
  onFeature: onFeature
};
<commit_msg>bug fix<commit_after>'use strict'

let log = require("./logger.js")(__filename, "info");

let fs = require('fs');
let f = require('./Firewalla.js');

const redis = require('redis')
const rclient = require('../util/redis_manager.js').getRedisClient()
const sclient = require('../util/redis_manager.js').getSubscriptionClient()
const pclient = require('../util/redis_manager.js').getPublishClient()

const async = require('asyncawait/async')
const await = require('asyncawait/await')

const dynamicConfigKey = "sys:features"

var dynamicConfigs = {}

let callbacks = {}

let config = null;

function getConfig() {
  if(!config) {
    let defaultConfig = JSON.parse(fs.readFileSync(f.getFirewallaHome() + "/net2/config.json", 'utf8'));
    let userConfigFile = f.getUserConfigFolder() + "/config.json";
    let userConfig = {};
    if(fs.existsSync(userConfigFile)) {
      userConfig = JSON.parse(fs.readFileSync(userConfigFile, 'utf8'));
    }

    let testConfig = {};
    if(process.env.NODE_ENV === 'test') {
      let testConfigFile = f.getUserConfigFolder() + "/config.test.json";
      if(fs.existsSync(testConfigFile)) {
        testConfig = JSON.parse(fs.readFileSync(testConfigFile, 'utf8'));
        log.warn("Test config is being used", testConfig, {});
      }
    }

    // user config will override system default config file
    config = Object.assign({}, defaultConfig, userConfig, testConfig);
  }
  return config;
}

function isFeatureOn_Static(featureName) {
  let config = getConfig()
  if(config.userFeatures && featureName in config.userFeatures) {
    if(config.userFeatures[featureName]) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

// undefined: feature not exists
// true: feature enabled
// false: feature disabled
function isFeatureOn_Dynamic(featureName) {
  if(dynamicConfigs && featureName in dynamicConfigs) {
    if(dynamicConfigs[featureName] === '1' ) {
      return true
    } else {
      return false
    }
  } else {
    return undefined
  }
}

function isFeatureOn(featureName) {
  const dynamicFlag = isFeatureOn_Dynamic(featureName)
  if(dynamicFlag !== undefined) {
    return dynamicFlag
  }

  const staticFlag = isFeatureOn_Static(featureName)
  if(staticFlag !== undefined) {
    return staticFlag
  } else {
    return false // default disabled
  }
}

function syncDynamicFeaturesConfigs() {
  return async(() => {
    let configs = await (rclient.hgetallAsync(dynamicConfigKey))
    if(configs) {
      dynamicConfigs = configs
    } else {
      dynamicConfigs = {}
    }
  })()
}

function enableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '1'))
    pclient.publish("config:feature:dynamic:enable", featureName)
    dynamicConfigs[featureName] = '1'
  })()
}

function disableDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hsetAsync(dynamicConfigKey, featureName, '0'))
    pclient.publish("config:feature:dynamic:disable", featureName)
    dynamicConfigs[featureName] = '0'
  })()
}

function clearDynamicFeature(featureName) {
  return async(() => {
    await (rclient.hdel(dynamicConfigKey, featureName))
    pclient.publish("config:feature:dynamic:clear", featureName)
    delete dynamicConfigs[featureName]
  })()
}

function getDynamicConfigs() {
  return dynamicConfigs
}

function getFeatures() {
  let staticFeatures = getConfig().userFeatures
  let dynamicFeatures = getDynamicConfigs()

  let x = {}

  let merged = Object.assign(x, staticFeatures, dynamicFeatures)

  for(let key in merged) {
    if(merged[key] == '0') {
      merged[key] = false
    }

    if(merged[key] == '1') {
      merged[key] = true
    }
  }

  const hiddenFeatures = getConfig().hiddenFeatures;

  if(hiddenFeatures && Array.isArray(hiddenFeatures)) {
    hiddenFeatures.forEach((f) => {
      if(f in merged) {
        delete merged[f];  // should be filtered out if hiddenFeatures contain the feature, this can force this feature not seen from app side
      }
    });
  }

  return merged
}

sclient.subscribe("config:feature:dynamic:enable")
sclient.subscribe("config:feature:dynamic:disable")
sclient.subscribe("config:feature:dynamic:clear")

sclient.on("message", (channel, message) => {
  log.info(`got message from ${channel}: ${message}`)
  const theFeature = message
  switch(channel) {
  case "config:feature:dynamic:enable":
    dynamicConfigs[theFeature] = '1'
    if(callbacks[theFeature]) {
      callbacks[theFeature].forEach((c) => {
        c(theFeature, true)
      })
    }
    break
  case "config:feature:dynamic:disable":
    dynamicConfigs[theFeature] = '0'
    if(callbacks[theFeature]) {
      callbacks[theFeature].forEach((c) => {
        c(theFeature, false)
      })
    }
    break
  case "config:feature:dynamic:clear":
    delete dynamicConfigs[theFeature]
    break
  }
});

syncDynamicFeaturesConfigs()

setInterval(() => {
  syncDynamicFeaturesConfigs()
}, 60 * 1000) // every minute

function onFeature(feature, callback) {
  if(!callbacks[feature]) {
    callbacks[feature] = []
  }

  callbacks[feature].push(callback)
}

module.exports = {
  getConfig: getConfig,
  isFeatureOn: isFeatureOn,
  getFeatures: getFeatures,
  getDynamicConfigs: getDynamicConfigs,
  enableDynamicFeature:enableDynamicFeature,
  disableDynamicFeature:disableDynamicFeature,
  clearDynamicFeature: clearDynamicFeature,
  syncDynamicFeaturesConfigs: syncDynamicFeaturesConfigs,
  onFeature: onFeature
};
<|endoftext|>


<commit_before>import React from 'react';
import { NavigationLink, RefreshLink } from 'navigation-react';

var People = ({ people, stateNavigator }) => {
    var rows = people.persons.map((person) => (

                <NavigationLink
                    stateKey="person"
                    navigationData={{ id: person.id }}
                    stateNavigator={stateNavigator}>
                    {person.name}
                </NavigationLink>

            {person.dateOfBirth}

    ));
    return (

                        Name
                        Date of Birth

{rows}

                Go to page
                <RefreshLink
                    navigationData={{ pageNumber: 1 }}
                    disableActive={true}
                    stateNavigator={stateNavigator}>
                    1
                </RefreshLink>
                <RefreshLink
                    navigationData={{ pageNumber: 2 }}
                    disableActive={true}
                    stateNavigator={stateNavigator}>
                    2
                </RefreshLink>

    );
};

var Person = ({ person, store, stateNavigator }) => {
    var handleChange = (event) => {
        store.dispatch({
            type: 'EDIT',
            name: event.target.value
        });
    };
    return (

            <NavigationBackLink
                distance={1}
                stateNavigator={stateNavigator}>
                Person Search
            </NavigationBackLink>

{person.name}

Date of Birth

                <input value={person.name} onChange={handleChange} />

Email

{person.email}

Phone

{person.phone}

    );
};

export { People, Person };<commit_msg>Tweaked export<commit_after>import React from 'react';
import { NavigationLink, RefreshLink } from 'navigation-react';

var People = ({ people, stateNavigator }) => {
    var rows = people.persons.map((person) => (

                <NavigationLink
                    stateKey="person"
                    navigationData={{ id: person.id }}
                    stateNavigator={stateNavigator}>
                    {person.name}
                </NavigationLink>

            {person.dateOfBirth}

    ));
    return (

                        Name
                        Date of Birth

{rows}

                Go to page
                <RefreshLink
                    navigationData={{ pageNumber: 1 }}
                    disableActive={true}
                    stateNavigator={stateNavigator}>
                    1
                </RefreshLink>
                <RefreshLink
                    navigationData={{ pageNumber: 2 }}
                    disableActive={true}
                    stateNavigator={stateNavigator}>
                    2
                </RefreshLink>

    );
};

var Person = ({ person, store, stateNavigator }) => {
    var handleChange = (event) => {
        store.dispatch({
            type: 'EDIT',
            name: event.target.value
        });
    };
    return (

            <NavigationBackLink
                distance={1}
                stateNavigator={stateNavigator}>
                Person Search
            </NavigationBackLink>

{person.name}

Date of Birth

                <input value={person.name} onChange={handleChange} />

Email

{person.email}

Phone

{person.phone}

    );
};

export default { Listing: People, Details: Person };<|endoftext|>


<commit_before>import React from 'react';
import {StyleSheet, ScrollView, Text, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import UIBarButtonIOS from './UIBarButtonIOS';

const colors = [
  'maroon', 'red', 'crimson', 'orange', 'brown', 'sienna', 'olive',
  'purple', 'fuchsia', 'indigo', 'green', 'navy', 'blue', 'teal', 'black'
];

export default () => (
  <NavigationContext.Consumer>
    {({data: {title}, stateNavigator}) => (
      <ScrollView contentInsetAdjustmentBehavior="automatic">
        <View style={styles.colors}>
          <UIBarButtonIOS title={title || "Hello"} onPress={() => {
            stateNavigator.navigate('grid', {title: 'World'})
          }} />
          <UIBarButtonIOS title="Again" />
          <UIBarButtonIOS title="And" />
          {colors.map(color => (
            <TouchableHighlight
              style={[
                {backgroundColor: color},
                styles.color
              ]}
              underlayColor={color}
              key={color}
              onPress={() => {
                stateNavigator.navigate('detail', {color});
              }}>
              <Text style={styles.text}>{color}</Text>
            </TouchableHighlight>
          ))}
        </View>
      </ScrollView>
    )}
  </NavigationContext.Consumer>
);

const styles = StyleSheet.create({
  colors: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'center',
    marginTop: 10,
  },
  color: {
    width: 100,
    height: 150,
    marginLeft: 10,
    marginRight: 10,
    marginBottom: 20,
    justifyContent: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 20,
    textAlign: 'center',
    fontWeight: 'bold',
  }
});<commit_msg>Toggled button text<commit_after>import React from 'react';
import {StyleSheet, ScrollView, Text, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import UIBarButtonIOS from './UIBarButtonIOS';

const colors = [
  'maroon', 'red', 'crimson', 'orange', 'brown', 'sienna', 'olive',
  'purple', 'fuchsia', 'indigo', 'green', 'navy', 'blue', 'teal', 'black'
];

export default () => (
  <NavigationContext.Consumer>
    {({data: {title}, stateNavigator}) => (
      <ScrollView contentInsetAdjustmentBehavior="automatic">
        <View style={styles.colors}>
          <UIBarButtonIOS title={title || "Hello"} onPress={() => {
            stateNavigator.navigate('grid', {title: title !== 'World' ? 'World' : 'Hello'})
          }} />
          <UIBarButtonIOS title="Again" />
          <UIBarButtonIOS title="And" />
          {colors.map(color => (
            <TouchableHighlight
              style={[
                {backgroundColor: color},
                styles.color
              ]}
              underlayColor={color}
              key={color}
              onPress={() => {
                stateNavigator.navigate('detail', {color});
              }}>
              <Text style={styles.text}>{color}</Text>
            </TouchableHighlight>
          ))}
        </View>
      </ScrollView>
    )}
  </NavigationContext.Consumer>
);

const styles = StyleSheet.create({
  colors: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'center',
    marginTop: 10,
  },
  color: {
    width: 100,
    height: 150,
    marginLeft: 10,
    marginRight: 10,
    marginBottom: 20,
    justifyContent: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 20,
    textAlign: 'center',
    fontWeight: 'bold',
  }
});<|endoftext|>


<commit_before>var FS = require('./../FamilySearch'),
    utils = require('./../utils');

/**
 * @ngdoc overview
 * @name places
 * @description
 * Functions for interacting with the FamilySearch Place Authority
 *
 * {@link https://familysearch.org/developers/docs/api/resources#places FamilySearch API Docs}
 */

/**
 * @ngdoc function
 * @name places.functions:getPlace
 *
 * @description
 * Get a place.
 *
 * - `getPlace()` - get the {@link places.types:constructor.PlaceDescription PlaceDescription} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_resource API Docs}
 *
 * @param {String} url full url of a place
 * @return {Object} promise for the response
 */
FS.prototype.getPlace = function(url) {
  var self = this;
  return self.plumbing.get(url).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.places, function(place, index, obj){
      obj[index] = self.createPlaceDescription(place);
    });
    return utils.extend(response, {
      getPlace: function() {
        return utils.maybe(data.places)[0];
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceDescription

 *
 * @description
 * Get a place.
 *
 * - `getPlaceDescription()` - get the {@link places.types:constructor.PlaceDescription PlaceDescription} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Description_resource API Docs}
 *
 *
 * @param {String} url full url of the place description
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceDescription = function(url) {
  var self = this;
  return self.plumbing.get(url).then(function(response){
    var data = utils.maybe(response.getData()),
        placesMap = {};

    utils.forEach(data.places, function(place, index, obj){
      obj[index] = placesMap[place.id] = self.createPlaceDescription(place);
    });

    utils.forEach(data.places, function(place){
      if(place.data.jurisdiction && place.data.jurisdiction.resource){
        var jurisdictionId = place.data.jurisdiction.resource.substring(1);
        if(placesMap[jurisdictionId]){
          place.setJurisdiction(placesMap[jurisdictionId]);
        }
      }
    });

    return utils.extend(response, {
      getPlaceDescription: function() {
        return utils.maybe(data.places)[0];
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlacesSearch

 *
 * @description
 * Search for a place.
 *
 * - `getSearchResults()` - get an array of {@link places.types:constructor.PlacesSearchResult PlacesSearchResults} from the response.
 *
 * __Search Parameters__
 *
 * * `start` - The index of the first search result for this page of results.
 * * `count` - The number of search results per page.
 * * `name`
 * * `partialName`
 * * `date`
 * * `typeId`
 * * `typeGroupId`
 * * `parentId`
 * * `latitude`
 * * `longitude`
 * * `distance`
 *
 * Read the {@link https://familysearch.org/developers/docs/api/places/Places_Search_resource API Docs} for more details on how to use the parameters.
 *
 *
 * @param {Object} params Search parameters
 * @return {Object} promise for the response
 */
FS.prototype.getPlacesSearch = function(params) {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-search').then(function(url){
    return self.plumbing.get(url, utils.removeEmptyProperties({
      q: utils.searchParamsFilter(utils.removeEmptyProperties(utils.extend({}, params))),
      start: params.start,
      count: params.count
    }), {'Accept': 'application/x-gedcomx-atom+json'});
  }).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.entries, function(entry, i, obj){
      obj[i] = self.createPlacesSearchResult(entry);
    });
    return utils.extend(response, {
      getSearchResults: function() {
        return utils.maybe(data.entries);
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceDescriptionChildren

 *
 * @description
 * Get the children of a Place Description. Use {@link places.functions:getPlaceSearch getPlacesSearch()} to filter by type, date, and more.
 *
 * - `getChildren()` - get an array of the {@link places.types:constructor.PlaceDescription PlaceDescriptions} (children) from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Description_Children_resource API Docs}
 *
 *
 * @param {String} url full url for the place descriptions children endpoint
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceDescriptionChildren = function(url) {
  var self = this;
  return self.plumbing.get(url).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.places, function(place, index, obj){
      obj[index] = self.createPlaceDescription(place);
    });
    return utils.extend(response, {
      getChildren: function() {
        return utils.maybe(data.places);
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceType

 *
 * @description
 * Get a place.
 *
 * - `getPlaceType()` - get the {@link vocabularies.types:constructor.VocabularyElement VocabularyElement} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Type_resource API Docs}
 *
 *
 * @param {String} id of the place
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceType = function(typeId) {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-type', {ptid: typeId}).then(function(url){
    return self.plumbing.get(url, {}, {'Accept': 'application/ld+json'});
  }).then(function(response){
    return utils.extend(response, {
      getPlaceType: function() {
        return self.createVocabularyElement(this.getData());
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypes

 *
 * @description
 * Get a list of all available Place Types.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} from the response
 * - `getPlaceTypes()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Types_resource API Docs}
 *
 *
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypes = function() {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-types').then(function(url){
    return self.plumbing.get(url, {}, {'Accept': 'application/ld+json'});
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypes: function() {
        return this.getList().getElements();
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypeGroup

 *
 * @description
 * Get a Place Type Group which includes a list of Places Types in the group.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} (Place Type Group) from the response
 * - `getPlaceTypes()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} (Place Types) in the group
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Types_resource API Docs}
 *
 *
 * @param {String} id of the place type group
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypeGroup = function(groupId) {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-type-group', {ptgid: groupId}).then(function(url){
    return self.plumbing.get(url, {}, {'Accept': 'application/ld+json'});
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypes: function() {
        return this.getList().getElements();
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypeGroups

 *
 * @description
 * Get a list of all available Place Types.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} from the response
 * - `getPlaceTypeGroups()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Type_Groups_resource API Docs}
 *
 *
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypeGroups = function() {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-type-groups').then(function(url){
    return self.plumbing.get(url, {}, {'Accept': 'application/ld+json'});
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypeGroups: function() {
        return this.getList().getElements();
      }
    });
  });
};<commit_msg>add param for language on places methods; close #173<commit_after>var FS = require('./../FamilySearch'),
    utils = require('./../utils');

/**
 * @ngdoc overview
 * @name places
 * @description
 * Functions for interacting with the FamilySearch Place Authority
 *
 * {@link https://familysearch.org/developers/docs/api/resources#places FamilySearch API Docs}
 */

/**
 * @ngdoc function
 * @name places.functions:getPlace
 *
 * @description
 * Get a place.
 *
 * - `getPlace()` - get the {@link places.types:constructor.PlaceDescription PlaceDescription} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_resource API Docs}
 *
 * @param {String} url full url of a place
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlace = function(url, lang) {
  var self = this;
  var headers = {};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.get(url, null, headers).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.places, function(place, index, obj){
      obj[index] = self.createPlaceDescription(place);
    });
    return utils.extend(response, {
      getPlace: function() {
        return utils.maybe(data.places)[0];
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceDescription

 *
 * @description
 * Get a place.
 *
 * - `getPlaceDescription()` - get the {@link places.types:constructor.PlaceDescription PlaceDescription} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Description_resource API Docs}
 *
 * @param {String} url full url of the place description
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceDescription = function(url, lang) {
  var self = this;
  var headers = {};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.get(url, null, headers).then(function(response){
    var data = utils.maybe(response.getData()),
        placesMap = {};

    utils.forEach(data.places, function(place, index, obj){
      obj[index] = placesMap[place.id] = self.createPlaceDescription(place);
    });

    utils.forEach(data.places, function(place){
      if(place.data.jurisdiction && place.data.jurisdiction.resource){
        var jurisdictionId = place.data.jurisdiction.resource.substring(1);
        if(placesMap[jurisdictionId]){
          place.setJurisdiction(placesMap[jurisdictionId]);
        }
      }
    });

    return utils.extend(response, {
      getPlaceDescription: function() {
        return utils.maybe(data.places)[0];
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlacesSearch

 *
 * @description
 * Search for a place.
 *
 * - `getSearchResults()` - get an array of {@link places.types:constructor.PlacesSearchResult PlacesSearchResults} from the response.
 *
 * __Search Parameters__
 *
 * * `start` - The index of the first search result for this page of results.
 * * `count` - The number of search results per page.
 * * `name`
 * * `partialName`
 * * `date`
 * * `typeId`
 * * `typeGroupId`
 * * `parentId`
 * * `latitude`
 * * `longitude`
 * * `distance`
 *
 * Read the {@link https://familysearch.org/developers/docs/api/places/Places_Search_resource API Docs} for more details on how to use the parameters.
 *
 *
 * @param {Object} params Search parameters
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlacesSearch = function(params, lang) {
  var self = this;
  var headers  = {'Accept': 'application/x-gedcomx-atom+json'};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.getCollectionUrl('FSPA', 'place-search').then(function(url){
    return self.plumbing.get(url, utils.removeEmptyProperties({
      q: utils.searchParamsFilter(utils.removeEmptyProperties(utils.extend({}, params))),
      start: params.start,
      count: params.count
    }), headers);
  }).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.entries, function(entry, i, obj){
      obj[i] = self.createPlacesSearchResult(entry);
    });
    return utils.extend(response, {
      getSearchResults: function() {
        return utils.maybe(data.entries);
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceDescriptionChildren

 *
 * @description
 * Get the children of a Place Description. Use {@link places.functions:getPlaceSearch getPlacesSearch()} to filter by type, date, and more.
 *
 * - `getChildren()` - get an array of the {@link places.types:constructor.PlaceDescription PlaceDescriptions} (children) from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Description_Children_resource API Docs}
 *
 * @param {String} url full url for the place descriptions children endpoint
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceDescriptionChildren = function(url, lang) {
  var self = this;
  var headers = {};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.get(url, null, headers).then(function(response){
    var data = utils.maybe(response.getData());
    utils.forEach(data.places, function(place, index, obj){
      obj[index] = self.createPlaceDescription(place);
    });
    return utils.extend(response, {
      getChildren: function() {
        return utils.maybe(data.places);
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceType

 *
 * @description
 * Get a place.
 *
 * - `getPlaceType()` - get the {@link vocabularies.types:constructor.VocabularyElement VocabularyElement} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Type_resource API Docs}
 *
 *
 * @param {String} id of the place
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceType = function(typeId, lang) {
  var self = this;
  var headers = {'Accept': 'application/ld+json'};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.getCollectionUrl('FSPA', 'place-type', {ptid: typeId}).then(function(url){
    return self.plumbing.get(url, {}, headers);
  }).then(function(response){
    return utils.extend(response, {
      getPlaceType: function() {
        return self.createVocabularyElement(this.getData());
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypes

 *
 * @description
 * Get a list of all available Place Types.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} from the response
 * - `getPlaceTypes()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Types_resource API Docs}
 *
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypes = function(lang) {
  var self = this;
  var headers = {'Accept': 'application/ld+json'};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.getCollectionUrl('FSPA', 'place-types').then(function(url){
    return self.plumbing.get(url, {}, headers);
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypes: function() {
        return this.getList().getElements();
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypeGroup

 *
 * @description
 * Get a Place Type Group which includes a list of Places Types in the group.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} (Place Type Group) from the response
 * - `getPlaceTypes()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} (Place Types) in the group
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Type_Group_resource API Docs}
 *
 *
 * @param {String} id of the place type group
 * @param {String} lang Optional. The language you want the display data returned in, when available. In the browser this defaults to the browser's language. On the server this defaults to 'en'.
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypeGroup = function(groupId, lang) {
  var self = this;
  var headers = {'Accept': 'application/ld+json'};
  if(lang){
    headers['Accept-Language'] = lang;
  }
  return self.plumbing.getCollectionUrl('FSPA', 'place-type-group', {ptgid: groupId}).then(function(url){
    return self.plumbing.get(url, {}, headers);
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypes: function() {
        return this.getList().getElements();
      }
    });
  });
};

/**
 * @ngdoc function
 * @name places.functions:getPlaceTypeGroups

 *
 * @description
 * Get a list of all available Place Types.
 *
 * - `getList()` - get the {@link vocabularies.types:constructor.VocabularyList VocabularyList} from the response
 * - `getPlaceTypeGroups()` - get an array of the {@link vocabularies.types:constructor.VocabularyElement VocabularyElements} from the response
 *
 * {@link https://familysearch.org/developers/docs/api/places/Place_Type_Groups_resource API Docs}
 *
 *
 * @return {Object} promise for the response
 */
FS.prototype.getPlaceTypeGroups = function() {
  var self = this;
  return self.plumbing.getCollectionUrl('FSPA', 'place-type-groups').then(function(url){
    return self.plumbing.get(url, {}, {'Accept': 'application/ld+json'});
  }).then(function(response){
    return utils.extend(response, {
      getList: function() {
        return self.createVocabularyList(this.getData());
      },
      getPlaceTypeGroups: function() {
        return this.getList().getElements();
      }
    });
  });
};<|endoftext|>


<commit_before>import fs from "fs-extra"
import path from "path";
import glob from "glob";
import {spawnSync} from "child_process";
import yargs from "yargs";

module.exports._copyBoilerplate = _copyBoilerplate;
module.exports.run = run;

function _copyBoilerplate(appDir) {
    const boilerplatePath = path.join(__dirname, "../../boilerplate/");
    const fromFiles = glob.sync(path.join(boilerplatePath, "**/{*,.gitkeep,.gitignore}"), {mark: true})
        // exclude directories
        .filter((fromPath) => fromPath[fromPath.length - 1] !== "/");

    // Copy boilerplate files if does not exists in appDir
    fromFiles.forEach((fromPath) => {
        const relatePath = fromPath.slice(boilerplatePath.length);
        const toPath = path.join(appDir, relatePath);

        if (! fs.existsSync(toPath)) {
            fs.copySync(fromPath, toPath);
        }
    });
}

function parseArgs(argv) {
    const parser = yargs
    .strict();

    return parser.parse(argv)
}

function run(argv) {
    const options = parseArgs(argv);

    const appDir = process.cwd();
    const packageJsonPath = path.join(appDir, "package.json");

    // copy files
    console.log("\u001b[36m[maya.js] Generate project files.\u001b[m");
    _copyBoilerplate(appDir);

    // npm init
    var npmInitReuslt = spawnSync("npm", ["init"], {stdio : "inherit"});

    if (npmInitReuslt.status !== 0) {
        console.error("\u001b[31m[maya.js] package.json setup failed.\u001b[m");
        return;
    }

    console.log("\u001b[32m[maya.js] Setup successful.");
    console.log("  Execute \u001b[32;7m`npm install`\u001b[m\u001b[32m and Let's fight \u001b[32;7m`maya cqc`\u001b[m! ");
}
<commit_msg>Now can use `maya init <init_dir>`<commit_after>import fs from "fs-extra";
import path from "path";
import glob from "glob";
import {spawnSync} from "child_process";
import yargs from "yargs";

module.exports._copyBoilerplate = _copyBoilerplate;
module.exports.run = run;

function _copyBoilerplate(appDir) {
    const boilerplatePath = path.join(__dirname, "../../boilerplate/");
    const fromFiles = glob.sync(path.join(boilerplatePath, "**/{*,.gitkeep,.gitignore}"), {mark: true, nodir: true});

    if (! fs.existsSync(appDir)) {
        fs.ensureDirSync(appDir);
    }

    // Copy boilerplate files if does not exists in appDir
    fromFiles.forEach((fromPath) => {
        const relatePath = fromPath.slice(boilerplatePath.length);
        const toPath = path.join(appDir, relatePath);

        if (! fs.existsSync(toPath)) {
            fs.copySync(fromPath, toPath);
        }
    });
}

function parseArgs(argv) {
    const parser = yargs
    .strict();

    return parser.parse(argv)
}

function run(argv) {
    const options = parseArgs(argv);

    const appDir = options._[0] ? path.join(process.cwd(), options._[0]) : process.cwd();
    const packageJsonPath = path.join(appDir, "package.json");

    // copy files
    console.log("\u001b[36m[maya.js] Generate project files.\u001b[m");
    _copyBoilerplate(appDir);

    // npm init
    var npmInitReuslt = spawnSync("npm", ["init"], {stdio : "inherit", cwd : appDir});

    if (npmInitReuslt.status !== 0) {
        console.error("\u001b[31m[maya.js] package.json setup failed.\u001b[m");
        return;
    }

    console.log("\u001b[32m[maya.js] Setup successful.");
    console.log("  Execute \u001b[32;7m`npm install`\u001b[m\u001b[32m and Let's fight \u001b[32;7m`maya cqc`\u001b[m! ");
}
<|endoftext|>


<commit_before>/**
 * kael.me.core.js - based on mootools(http://mootools.net) compact javascript framework.
 * author  Kael Zhang[i@kael.me]

 * copyright:
 * - All rights reserved.
 * - Copyright (c) 2009 - 2011 [Kael Zhang](http://kael.me).
 */

/**
 * corek
 * mt.js -> km.js -> lang.js -> web.js -> loader.js -> config.js
 *
 */

/**
 * module core
 */

/**
 * @param {undefined=} undef
 */
;(function(host, K, undef){

var seed = host && host[K] || {},

    // no operation
    NOOP = function(){}, EMPTY = '',

    /**
	 * copy all properties in the supplier to the receiver
	 * @param r {Object} receiver
	 * @param s {Object} supplier
	 * @param or {boolean=} whether override the existing property in the receiver
	 * @param cl {(Array.<string>)=} copy list, an array of selected properties
	 */
	mix = function (r, s, or, cl) {
		if (!s || !r) return r;
		var i = 0, c, len;
		or = or || or === undef;

		if (cl && (len = cl.length)) {
			for (; i < len; i++) {
				c = cl[i];
				if ( (c in s) && (or || !(c in r) ) ) {
					r[c] = s[c];
				}
			}
		} else {
			for (c in s) {
				if (or || !(c in r)) {
					r[c] = s[c];
				}
			}
		}
		return r;
	},

	_guid = 1;

// actually, K must be an object, or override it
K = host[K] = seed;

mix(K, {

	// @const
	__HOST: K.__HOST || host,

	build: '%buildtime%',

	mix: mix,

	guid: function(){
		return _guid ++;
	},

    /**
     * deprecated mootools methods

     * deprecated
     * $chk:
     * $defined:     removed, please simply use "obj !== undefined" instead
     * $arguments:   uesless! removed
     * $empty:       useless, use "function(){}" instead, no querying for scope chain
     * $clear:       useless, use clearTimeout or clearInterval instead
     */

    // if debug mode is off, KM.log & KM.error will do nothing
	log: NOOP,
    error: NOOP,

    /**
     * Creates specified namespace if it doesn't exist

     *
     *    KM.namespace('widget.Logger'); // returns KM.widget.Logger
     *    KM.namespace('KM.widget.Logger'); // returns KM.widget.Logger
     *

     * @return {Object} current app namespace
     */
    namespace: function(){
        var args = arguments, self = this, h = self.__HOST,
            root = null,

            i = 0, i_len = args.length,
            j, j_len,

            ns;

        for(; i < i_len; i ++ ){
            ns = (EMPTY + args[i]).split('.');
			root = self;
            j_len = ns.length;

            for(j = (h[ns[0]] === self ? 1 : 0); j < j_len; j ++){
                root[ns[j]] = root[ns[j]] || {};
                root = root[ns[j]];
            }
        }

        return root;
    },

    // load 'log' module to switch debug-mode on
    _debugOn: function(){
        // K.provide('log', function(K){ K.log('debug module attached') });
        K._Config.debug = true;
    }

});

})(this, 'KM');

KM.namespace('UA', '_Config');

/**

 2010-08-16
 TODO:
 √ GLOBAL: remove all native implements of non-ECMAScript5 standards

 * change log:
 * 2011-04-19  Kael: move KM.type to lang.js
 * 2011-04-01  Kael Zhang: add adapter for typeOf of mootools
 * 2010-12-13  Kael Zhang: fix the getter of KM.data
 * 2010-10-09  Kael Zhang: 创建文件
 */<commit_msg>change comments<commit_after>/**
 * kael.me.core.js - based on mootools(http://mootools.net) compact javascript framework.
 * author  Kael Zhang[i@kael.me]

 * copyright:
 * - All rights reserved.
 * - Copyright (c) 2009 - 2011 [Kael Zhang](http://kael.me).
 */

/**
 * corek
 * mt.js -> core.js -> lang.js -> web.js -> loader.js -> config.js
 *
 */

/**
 * module core
 */

/**
 * @param {undefined=} undef
 */
;(function(host, K, undef){

var seed = host && host[K] || {},

    // no operation
    NOOP = function(){}, EMPTY = '',

    /**
	 * copy all properties in the supplier to the receiver
	 * @param r {Object} receiver
	 * @param s {Object} supplier
	 * @param or {boolean=} whether override the existing property in the receiver
	 * @param cl {(Array.<string>)=} copy list, an array of selected properties
	 */
	mix = function (r, s, or, cl) {
		if (!s || !r) return r;
		var i = 0, c, len;
		or = or || or === undef;

		if (cl && (len = cl.length)) {
			for (; i < len; i++) {
				c = cl[i];
				if ( (c in s) && (or || !(c in r) ) ) {
					r[c] = s[c];
				}
			}
		} else {
			for (c in s) {
				if (or || !(c in r)) {
					r[c] = s[c];
				}
			}
		}
		return r;
	},

	_guid = 1;

// actually, K must be an object, or override it
K = host[K] = seed;

mix(K, {

	// @const
	__HOST: K.__HOST || host,

	build: '%buildtime%',

	mix: mix,

	guid: function(){
		return _guid ++;
	},

    /**
     * deprecated mootools methods

     * deprecated
     * $chk:
     * $defined:     removed, please simply use "obj !== undefined" instead
     * $arguments:   uesless! removed
     * $empty:       useless, use "function(){}" instead, no querying for scope chain
     * $clear:       useless, use clearTimeout or clearInterval instead
     */

    // if debug mode is off, KM.log & KM.error will do nothing
	log: NOOP,
    error: NOOP,

    /**
     * Creates specified namespace if it doesn't exist

     *
     *    KM.namespace('widget.Logger'); // returns KM.widget.Logger
     *    KM.namespace('KM.widget.Logger'); // returns KM.widget.Logger
     *

     * @return {Object} current app namespace
     */
    namespace: function(){
        var args = arguments, self = this, h = self.__HOST,
            root = null,

            i = 0, i_len = args.length,
            j, j_len,

            ns;

        for(; i < i_len; i ++ ){
            ns = (EMPTY + args[i]).split('.');
			root = self;
            j_len = ns.length;

            for(j = (h[ns[0]] === self ? 1 : 0); j < j_len; j ++){
                root[ns[j]] = root[ns[j]] || {};
                root = root[ns[j]];
            }
        }

        return root;
    },

    // load 'log' module to switch debug-mode on
    _debugOn: function(){
        // K.provide('log', function(K){ K.log('debug module attached') });
        K._Config.debug = true;
    }

});

})(this, 'KM');

KM.namespace('UA', '_Config');

/**

 2010-08-16
 TODO:
 √ GLOBAL: remove all native implements of non-ECMAScript5 standards

 * change log:
 * 2011-04-19  Kael: move KM.type to lang.js
 * 2011-04-01  Kael Zhang: add adapter for typeOf of mootools
 * 2010-12-13  Kael Zhang: fix the getter of KM.data
 * 2010-10-09  Kael Zhang: 创建文件
 */<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////////////////////////////
//   (C)opyright Heark Gaming Co.                                                                   //
//   RPG Script v0.6                                                                                //
//   This is the updated version of Heark's RPG Script                                              //
// See Original script here: https://raw.githubusercontent.com/Heark/rpgtextbased/master/scripts.js //
//   Authored on 9/??/2014                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////////////

// info gather
var name = prompt("what is your name?")

// creating players
var player = function(name, health, attack, defense, specialattack, specialdefense){
    this.name = name;
    this.health = health;
    this.attack = attack;
    this.defense = defense;
    this.specialattack = specialattack;
    this.specialdefense = specialdefense;
}
// moves
var move = function(name, damage, accuracy){
    this.name = name;
    this.damage = damage;
    this.accuracy = accuracy;
}
var healmove = function(range, accuracy){
    this.range = range;
    this.accuracy = accuracy;
}
// creating enemies
var enemy = function(name, health, attack, defense, specialattack, specialdefense){
    this.name = name;
    this.health = health;
    this.attack = attack;
    this.defense = defense;
    this.specialattack = specialattack;
    this.specialdefense = specialdefense;
}
var evilcat = new enemy("Evil Cat", 40, 3, 4, 3, 4)
var dragon = new enemy("Dragon", 135, 5, 4, 3, 4)
var orc = new enemy("Orc", 85, 1, 1, 1, 1)
var ogre = new enemy("Ogre", 105, 3, 4, 4, 5)
// creating the skills
var punch = new move("Punch",10,100)
var kick = new move("Kick",15,85)
var wisp = new move("wisp",12,100)
var minorheal = new healmove(5,100)
var scratch = new move("Scratch",2,100)
// class creation
var classmessage = alert("Availiable classes are: Paladin, Mage, Marksman")
var userclass = prompt("Please Choose your class.")
if (userclass == "Paladin" || "paladin"){
    var user = new player(100, 12, 10, 5, 6)
    var skills = [punch, kick]
}
else if (userclass == "Mage" || "mage"){
    var user = new player(100, 6, 6, 14, 11)
    var skills = [wisp, minorheal]
}
// items
var item = function(name, description, damage, heal){
    this.name = name;
    this.description = description;
    this.damage = damage;
    this.heal = heal;
}
var minorpotion = new item("Minor Potion", "Heal by 45pts", 0, 45);
var majorpotion = new item("Major Potion", "Heal by 85pts", 0, 85);
var bomb = new item("Bomb", "Explodes and does 30 damage to one enemy.", 30, 0);

// inventory
var inventory = [];

// battle mod
var randnum = Math.floor(Math.random(10)*10);

// battle script
// Part 1

console.log('Cat appeared!')
var battle = function(enemy, player){

}
if (randnum > 5){
    catbattle = true
} else {
    console.log("No Fight!");
}
if (catbattle = true){
    console.log('Cat appeared!');
}
    Array.prototype.contains = function(elem)
{
   for (var i in this)
   {
       if (this[i] == elem) return true;
   }
   return false;
}
if (catbattle = true) do {
    var input = prompt("What do you do!?");
if (input == "Inventory"){
    console.log("Commands: Inventory, " +skills.name+ ".");
    alert("Your Items are" +inventory.name+ ".");
    var iteminput = prompt("What Item would you like to use?");
    if (iteminput == "Bomb"){
        if (inventory.contains(bomb)){
            console.log("You threw a bomb at" +evilcat.name+ ".");
            evilcat.health = evilcat.health - bomb.damage;
        }
    }
}
else { console.log("You don't have this item!");
input;
    }
}
while (evilcat.health <= 0);

<commit_msg>Update scripts.js<commit_after>//////////////////////////////////////////////////////////////////////////////////////////////////////
//   (C)opyright Heark Gaming Co.                                                                   //
//   RPG Script v0.6                                                                                //
//   This is the updated version of Heark's RPG Script                                              //
// See Original script here: https://raw.githubusercontent.com/Heark/rpgtextbased/master/scripts.js //
//   Authored on 9/??/2014                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////////////

// info gather
var name = prompt("what is your name?")

// creating players
var player = function(name, health, attack, defense, specialattack, specialdefense){
    this.health = health;
    this.attack = attack;
    this.defense = defense;
    this.specialattack = specialattack;
    this.specialdefense = specialdefense;
}
// moves
var move = function(name, damage, accuracy){
    this.name = name;
    this.damage = damage;
    this.accuracy = accuracy;
}
var healmove = function(range, accuracy){
    this.range = range;
    this.accuracy = accuracy;
}
// creating enemies
var enemy = function(name, health, attack, defense, specialattack, specialdefense){
    this.name = name;
    this.health = health;
    this.attack = attack;
    this.defense = defense;
    this.specialattack = specialattack;
    this.specialdefense = specialdefense;
}
var evilcat = new enemy("Evil Cat", 40, 3, 4, 3, 4)
var dragon = new enemy("Dragon", 135, 5, 4, 3, 4)
var orc = new enemy("Orc", 85, 1, 1, 1, 1)
var ogre = new enemy("Ogre", 105, 3, 4, 4, 5)
// creating the skills
var punch = new move("Punch",10,100)
var kick = new move("Kick",15,85)
var wisp = new move("wisp",12,100)
var minorheal = new healmove(5,100)
var scratch = new move("Scratch",2,100)
// class creation
var classmessage = alert("Availiable classes are: Paladin, Mage, Marksman")
var userclass = prompt("Please Choose your class.")
if (userclass == "Paladin" || "paladin"){
    var user = new player(100, 12, 10, 5, 6)
    var skills = [punch, kick]
}
else if (userclass == "Mage" || "mage"){
    var user = new player(100, 6, 6, 14, 11)
    var skills = [wisp, minorheal]
}
// items
var item = function(name, description, damage, heal){
    this.name = name;
    this.description = description;
    this.damage = damage;
    this.heal = heal;
}
var minorpotion = new item("Minor Potion", "Heal by 45pts", 0, 45);
var majorpotion = new item("Major Potion", "Heal by 85pts", 0, 85);
var bomb = new item("Bomb", "Explodes and does 30 damage to one enemy.", 30, 0);

// inventory
var inventory = [];

// battle mod
var randnum = Math.floor(Math.random(10)*10);

// battle script
// Part 1

console.log('Cat appeared!')
var battle = function(enemy, player){

}
if (randnum > 5){
    catbattle = true
} else {
    console.log("No Fight!");
}
if (catbattle = true){
    console.log('Cat appeared!');
}
    Array.prototype.contains = function(elem)
{
   for (var i in this)
   {
       if (this[i] == elem) return true;
   }
   return false;
}
if (catbattle = true) do {
    var input = prompt("What do you do!?");
if (input == "Inventory"){
    console.log("Commands: Inventory, " +skills.name+ ".");
    alert("Your Items are" +inventory.name+ ".");
    var iteminput = prompt("What Item would you like to use?");
    if (iteminput == "Bomb"){
        if (inventory.contains(bomb)){
            console.log("You threw a bomb at" +evilcat.name+ ".");
            evilcat.health = evilcat.health - bomb.damage;
        }
    }
}
else { console.log("You don't have this item!");
input;
    }
}
while (evilcat.health <= 0);

<|endoftext|>


<commit_before>require('dotenv').config();

const path = require('path');
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');
const withSass = require('@zeit/next-sass');
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');
const Dotenv = require('dotenv-webpack');

const nextConfig = {
  webpack: (config) => {
    config.plugins = [
      ...config.plugins,
      new Dotenv({
        path: path.join(__dirname, '.env'),
        systemvars: true,
      }),
    ];

    // mini-css-extract-plugin generates a warning when importing css as modules
    // as we scope manually we can ignore this warning: https://github.com/zeit/next-plugins/issues/506#issuecomment-589269285
    config.plugins.push(
      new FilterWarningsPlugin({
        exclude: /mini-css-extract-plugin[^]*Conflicting order between:/,
      })
    );

    config.node = {
      fs: 'empty',
    };

    return config;
  },
  redirects: async () => [
    {
      source: '/dashboards/',
      destination: `/dashboards/global/`,
      permanent: true,
    },
    {
      source: '/topics/',
      destination: `/topics/biodiversity/`,
      permanent: true,
    },
    {
      source: '/grants-and-fellowships/',
      destination: `/grants-and-fellowships/projects/`,
      permanent: true,
    },
  ],
  rewrites: async () => [
    {
      source: '/howto/',
      destination: `https://vizzuality.github.io/gfw-howto/`,
    },
    {
      source: '/howto/:path*/',
      destination: `https://vizzuality.github.io/gfw-howto/:path*/`,
    },
    {
      source: '/howto/:path*',
      destination: `https://vizzuality.github.io/gfw-howto/:path*`,
    },
    {
      source: '/help/',
      destination: `http://localhost:3001/help/`,
    },
    {
      source: '/help/:path*/',
      destination: `http://localhost:3001/help/:path*/`,
    },
    {
      source: '/help/:path*',
      destination: `http://localhost:3001/help/:path*`,
    },
    {
      source: '/map/',
      destination: '/map/global/',
    },
    {
      source: '/embed/map/',
      destination: '/embed/map/global/',
    },
    {
      source: '/my-gfw/:path*/',
      destination: '/my-gfw/',
    },
  ],
  trailingSlash: true,
};

module.exports = withPlugins(
  [[withSass], [optimizedImages], [withBundleAnalyzer]],
  nextConfig
);
<commit_msg>update to prod help center<commit_after>require('dotenv').config();

const path = require('path');
const withPlugins = require('next-compose-plugins');
const optimizedImages = require('next-optimized-images');
const withSass = require('@zeit/next-sass');
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});
const FilterWarningsPlugin = require('webpack-filter-warnings-plugin');
const Dotenv = require('dotenv-webpack');

const nextConfig = {
  webpack: (config) => {
    config.plugins = [
      ...config.plugins,
      new Dotenv({
        path: path.join(__dirname, '.env'),
        systemvars: true,
      }),
    ];

    // mini-css-extract-plugin generates a warning when importing css as modules
    // as we scope manually we can ignore this warning: https://github.com/zeit/next-plugins/issues/506#issuecomment-589269285
    config.plugins.push(
      new FilterWarningsPlugin({
        exclude: /mini-css-extract-plugin[^]*Conflicting order between:/,
      })
    );

    config.node = {
      fs: 'empty',
    };

    return config;
  },
  redirects: async () => [
    {
      source: '/dashboards/',
      destination: `/dashboards/global/`,
      permanent: true,
    },
    {
      source: '/topics/',
      destination: `/topics/biodiversity/`,
      permanent: true,
    },
    {
      source: '/grants-and-fellowships/',
      destination: `/grants-and-fellowships/projects/`,
      permanent: true,
    },
  ],
  rewrites: async () => [
    {
      source: '/howto/',
      destination: `https://vizzuality.github.io/gfw-howto/`,
    },
    {
      source: '/howto/:path*/',
      destination: `https://vizzuality.github.io/gfw-howto/:path*/`,
    },
    {
      source: '/howto/:path*',
      destination: `https://vizzuality.github.io/gfw-howto/:path*`,
    },
    {
      source: '/help/',
      destination: `https://gfw-help-center.herokuapp.com/help/`,
    },
    {
      source: '/help/:path*/',
      destination: `https://gfw-help-center.herokuapp.com/help/:path*/`,
    },
    {
      source: '/help/:path*',
      destination: `https://gfw-help-center.herokuapp.com/help/:path*`,
    },
    {
      source: '/map/',
      destination: '/map/global/',
    },
    {
      source: '/embed/map/',
      destination: '/embed/map/global/',
    },
    {
      source: '/my-gfw/:path*/',
      destination: '/my-gfw/',
    },
  ],
  trailingSlash: true,
};

module.exports = withPlugins(
  [[withSass], [optimizedImages], [withBundleAnalyzer]],
  nextConfig
);
<|endoftext|>


<commit_before> var NodeHelper = require("node_helper");
 var request = require('request');

module.exports = NodeHelper.create({
	init: function() {
		console.log('Initializing mm-background module helper ...');
	},

	socketNotificationReceived: function(notification, payload) {
		console.log('getImagesFromDirectory');

		if (notification === 'IMAGES_GET') {
			var self = this;

			console.log('getImagesFromDirectory');
			//var fs = require('fs');
			var recursive = require('recursive-readdir');
			var images = {}
			images.photo = new Array();

			recursive('modules/MMM-RandomBackground/photos/', function (err, data) {
				console.log('Loaded1 ' + data.length + ' images.');
				for (i = 0; i < data.length; i++) {
					console.log('Data: ' + data[i]);

					images.photo.push({
						'photolink': data[i]
					});
				}

				console.log('Loaded2 ' + images.photo.length + ' images.');
				self.sendSocketNotification('IMAGE_LIST', images);
			});

			/*fs.readdir('modules/mmm-background/photos/Roadtrip-2014/Dave', (err, data) => {

				console.log('Loaded1 ' + data.length + ' images.');
				for (i = 0; i < data.length; i++) {
					//console.log('Data: ' + data[i]);

					images.photo.push({
						'photolink': 'modules/mmm-background/photos/Roadtrip-2014/Dave/' + data[i]
					});
				}

				console.log('Loaded2 ' + images.photo.length + ' images.');
				self.sendSocketNotification('IMAGE_LIST', images);
			});*/
		}
	}
});<commit_msg>Removed some logging<commit_after> var NodeHelper = require("node_helper");
 var request = require('request');

module.exports = NodeHelper.create({
	init: function() {
		console.log('Initializing mm-background module helper ...');
	},

	socketNotificationReceived: function(notification, payload) {
		if (notification === 'IMAGES_GET') {
			var self = this;

			var recursive = require('recursive-readdir');
			var images = {}
			images.photo = new Array();

			recursive('modules/MMM-RandomBackground/photos/', function (err, data) {
				if (data.length > 0) {
					for (i = 0; i < data.length; i++) {
						images.photo.push({
							'photolink': data[i]
						});
					}
				} else {
					console.log('No photo\'s found, make sure there is a folder called \'photos\' in this directory');
				}

				console.log('Loaded ' + images.photo.length + ' images.');
				self.sendSocketNotification('IMAGE_LIST', images);
			});
		}
	}
});<|endoftext|>


<commit_before>function addslashes (str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ates Goral (http://magnetiq.com)
    // +   improved by: marrtins
    // +   improved by: Nate
    // +   improved by: Onno Marsman
    // +   input by: Denny Wardhana
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // *     example 1: addslashes("kevin's birthday");
    // *     returns 1: 'kevin\'s birthday'

    return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\u0000/g, "\\0");
}<commit_msg>Simplified addslashes (thanks Oskar Larsson Högfeldt!)<commit_after>function addslashes (str) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Ates Goral (http://magnetiq.com)
    // +   improved by: marrtins
    // +   improved by: Nate
    // +   improved by: Onno Marsman
    // +   input by: Denny Wardhana
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Oskar Larsson Hgfeldt (http://oskar-lh.name/)
    // *     example 1: addslashes("kevin's birthday");
    // *     returns 1: 'kevin\'s birthday'

    return (str+'').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0');
}<|endoftext|>


<commit_before>function strip_tags (str, allowed_tags) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Luke Godfrey
    // +      input by: Pul
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Onno Marsman
    // +      input by: Alex
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Marc Palau
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Eric Nagel
    // +      input by: Bobby Drake
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Tomasz Wesolowski
    // *     example 1: strip_tags('
Kevin

van Zonneveld', '');
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: strip_tags('
Kevin van Zonneveld
', '
');
    // *     returns 2: '
Kevin van Zonneveld
'
    // *     example 3: strip_tags("Kevin van Zonneveld", "");
    // *     returns 3: 'Kevin van Zonneveld'
    // *     example 4: strip_tags('1 < 5 5 > 1');
    // *     returns 4: '1 < 5 5 > 1'

    var key = '', allowed = false;
    var matches = [];
    var allowed_array = [];
    var allowed_tag = '';
    var i = 0;
    var k = '';
    var html = '';

    var replacer = function (search, replace, str) {
        return str.split(search).join(replace);
    };

    // Build allowes tags associative array
    if (allowed_tags) {
        allowed_array = allowed_tags.match(/([a-zA-Z0-9]+)/gi);
    }

    str += '';

    // Match tags
    matches = str.match(/(<\/?[\S][^>]*>)/gi);

    // Go through all HTML tags
    for (key in matches) {
        if (isNaN(key)) {
            // IE7 Hack
            continue;
        }

        // Save HTML tag
        html = matches[key].toString();

        // Is tag not in allowed list? Remove from str!
        allowed = false;

        // Go through all allowed tags
        for (k in allowed_array) {
            // Init
            allowed_tag = allowed_array[k];
            i = -1;

            if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+'>');}
            if (i != 0) { i = html.toLowerCase().indexOf('<'+allowed_tag+' ');}
            if (i != 0) { i = html.toLowerCase().indexOf('</'+allowed_tag)   ;}

            // Determine
            if (i == 0) {
                allowed = true;
                break;
            }
        }

        if (!allowed) {
            str = replacer(html, "", str); // Custom replace. No regexing
        }
    }

    return str;
}<commit_msg>Refactored strip_tags (thanks Rafał Kukawski<commit_after>function strip_tags (input, allowed) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Luke Godfrey
    // +      input by: Pul
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Onno Marsman
    // +      input by: Alex
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Marc Palau
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Eric Nagel
    // +      input by: Bobby Drake
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Tomasz Wesolowski
    // +      input by: Evertjan Garretsen
    // +    revised by: Rafał Kukawski (http://blog.kukawski.pl/)
    // *     example 1: strip_tags('
Kevin

van Zonneveld', '');
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: strip_tags('
Kevin van Zonneveld
', '
');
    // *     returns 2: '
Kevin van Zonneveld
'
    // *     example 3: strip_tags("Kevin van Zonneveld", "");
    // *     returns 3: 'Kevin van Zonneveld'
    // *     example 4: strip_tags('1 < 5 5 > 1');
    // *     returns 4: '1 < 5 5 > 1'
    // *     example 5: strip_tags('1
 1');
    // *     returns 5: '1  1'
    // *     example 6: strip_tags('1
 1', '
');
    // *     returns 6: '1  1'
    // *     example 7: strip_tags('1
 1', '

');
    // *     returns 7: '1
 1'

	   allowed = (((allowed || "") + "")
	      .toLowerCase()
	      .match(/<[a-z][a-z0-9]*>/g) || [])
	      .join(''); // making sure the allowed arg is a string containing only tags in lowercase (<c>)
	   var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi,
	       commentsAndPhpTags = /|<\?(?:php)?[\s\S]*?\?>/gi;
	   return input.replace(commentsAndPhpTags, '').replace(tags, function($0, $1){
	      return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : '';
	   });
	}<|endoftext|>


<commit_before>export class Mql {
  constructor() {
    this.init = function () {
      if (!this.afterElement) {
        // If the browser doesn't support window.getComputedStyle just return
        return;
      }
      this._resizeListener(); // eslint-disable-line no-underscore-dangle
    };

    this._resizeListener = function () { // eslint-disable-line no-underscore-dangle
      $(window).on('resize orientationchange load', () => {
        this.currentBreakpoint = this.afterElement.getPropertyValue('content');
        if (this.currentBreakpoint !== this.lastBreakpoint) {
          $(window).trigger('breakpoint-change', this.currentBreakpoint);
          this.lastBreakpoint = this.currentBreakpoint;
        }
      });
    };
  }
  // end of constructor

  MediaQueryListener() {
    this.afterElement = window.getComputedStyle ? window.getComputedStyle(document.body, ':after') : false;
    this.currentBreakpoint = '';
    this.lastBreakpoint = '';
    this.init();
  }
}

// element[string], target[obj]
export function sticky(e, t) {
  t.bind('load', () => {
    let eHeight = 0;
    let eTop = 0;
    let $e = $(e);

    function pos() {
      eHeight = $e.height();
      eTop = t.scrollTop()+t.height()-eHeight+'px';
      if ($(document.body).height() < t.height()) {
        $e.css({
          position: 'absolute'
        }).animate({
          top: eTop
        });
      } else {
        $e.css({
          position: 'static'
        });
      }
    }

    pos();
    $(window).scroll(pos).resize(pos);
  });
    // end of bind
}
  // end of ids.sticky
<commit_msg>ADD: Sticky fn<commit_after>export class Mql {
  constructor() {
    this.init = function () {
      if (!this.afterElement) {
        // If the browser doesn't support window.getComputedStyle just return
        return;
      }
      this._resizeListener(); // eslint-disable-line no-underscore-dangle
    };

    this._resizeListener = function () { // eslint-disable-line no-underscore-dangle
      $(window).on('resize orientationchange load', () => {
        this.currentBreakpoint = this.afterElement.getPropertyValue('content');
        if (this.currentBreakpoint !== this.lastBreakpoint) {
          $(window).trigger('breakpoint-change', this.currentBreakpoint);
          this.lastBreakpoint = this.currentBreakpoint;
        }
      });
    };
  }
  // end of constructor

  MediaQueryListener() {
    this.afterElement = window.getComputedStyle ? window.getComputedStyle(document.body, ':after') : false;
    this.currentBreakpoint = '';
    this.lastBreakpoint = '';
    this.init();
  }
}

// element[string], target[obj]
export function sticky(e, t) {
  t.bind('load', () => {
    let eHeight = 0;
    let eTop = 0;
    let $e = $(e);

    function pos() {
      eHeight = $e.height();
      eTop = t.scrollTop()+t.height()-eHeight+'px';
      if ($(document.body).height() < t.height()) {
        $e.css({
          position: 'absolute'
        }).animate({
          top: eTop
        });
      } else {
        $e.css({
          position: 'static'
        });
      }
    }

    pos();
    $(window).scroll(pos).resize(pos);
  });
  // end of bind
}
// end of ids.sticky

export function toggleTop(obj, evt) {
  console.log('in toggletop');
  document.getElementById(obj).addEventListener(evt, (e) => {
    e.preventDefault();
    $('nav').animate({
      height: 'toggle'
    }, 200, () => {
    ($('nav').is(':visible')) ? $('article').css('display', 'none') : $('article').css('display', 'block');
    });
    // end of nav.animate
  }, false);
}
// end of ids.nav
<|endoftext|>


<commit_before>/* taskStatus.js
 * ---------------------------------------------
 * Handles status of the task ("started", "not_started", "delayed", "completed")
 * Formerly completeTask.js
 */

 //TASK STATUS COLORS
 var TASK_NOT_START_COLOR = "#C9C9C9";
 var TASK_START_COLOR = "blue";
 var TASK_DELAY_COLOR = "red";
 var TASK_COMPLETE_COLOR = "green";

//Fires on "Start" button on task modal
 function startTask(groupNum) {
    var indexOfJSON = getEventJSONIndex(groupNum);
    var eventObj = flashTeamsJSON["events"][indexOfJSON];
    eventObj.status = "started";

    //START TIMER
    //START HERE ALEXANDRA

    updateStatus();
    drawEvent(eventObj); //Will update color
 }

//Alert firing on event complete buttons
function confirmCompleteTask(groupNum) {
    //Close the first (task) modal
    $("#task_modal").modal('hide');

    //Creates the alert modal title
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Have You Completed This Task?";

    //Gets information from event using id
    var indexOfJSON = getEventJSONIndex(groupNum);
    var events = flashTeamsJSON["events"];
    var eventToComplete = events[indexOfJSON];

    //Edits the confirmAction modal from _confirm_action.html.erb
    var alertText = document.getElementById("confirmActionText");
    alertText.innerHTML = completeTaskModalText(eventToComplete);

    //Code for the Task Completed Button
    var completeButton = document.getElementById("confirmButton");
    completeButton.innerHTML = "Task Completed";
    $("#confirmButton").attr("class","btn btn-success");
    if (eventToComplete.outputs != null && eventToComplete.outputs != "") {
        $("#confirmButton").prop('disabled', true); //Defaults to disabled
    }
    $('#confirmAction').modal('show');

    //Set change function on checkboxes, enable button if all checkboxes are checked
    $(".outputCheckbox").change(function() {
        var totalCheckboxes = $(".outputCheckbox").length;
        var checkedCheckboxes = $(".outputCheckbox:checked").length;
        if (totalCheckboxes == checkedCheckboxes) {
            $("#confirmButton").prop('disabled', false);
        } else {
            $("#confirmButton").prop('disabled', true);
        }
    });

    //Calls completeTask function if user confirms the complete
    document.getElementById("confirmButton").onclick=function(){
    	$('#confirmAction').modal('hide');
    	completeTask(groupNum);
    };
    hidePopover(groupNum);
}

//Return text to fill complete task modal
function completeTaskModalText(eventToComplete) {
    var modalText = "Outputs for " + eventToComplete["title"] + ":";

    //Get outputs from eventObj
    var eventOutputs = eventToComplete.outputs;
    if (eventOutputs != null && eventOutputs != "") {
        eventOutputs = eventToComplete.outputs.split(",");
    }

    //Create Checklist of outputs
    modalText += "<form id='event_checklist_" + eventToComplete.id + "' >";
    if (eventOutputs == null || eventOutputs == "") {
        modalText += "No outputs were specified for this task.";
    } else {
        for (i=0; i<eventOutputs.length; i++) {
            modalText += "<input type='checkbox' class='outputCheckbox'>" + eventOutputs[i] + "</input>
";
        }
    }
    modalText += "</form>";

    modalText+= "
Click 'Task Completed' to alert the PC and move on to the documentation questons."
    return modalText;
}

//Called when user confirms event completion alert
var completeTask = function(groupNum){
    //Update the status of a task
    var indexOfJSON = getEventJSONIndex(groupNum);
    var eventToComplete = flashTeamsJSON["events"][indexOfJSON];
    eventToComplete.status = "completed";

    //TODO: Iteration Marker - if we iterate and want to put it on the task, do it here

    //Update database, must be false b/c we are not using the old ticker
    updateStatus(false);
    drawEvent(eventToComplete);

    //Message the PC that the task has been completed
    //TODO

    //Guide worker to documentation questions
    //TODO

    //------------------------------//
    //OLD TICKER VERSION CODE, TO DELETE LATER, USE TO MAKE SURE NOT MISSING CASES??
    /*
    $('#confirmAction').modal('hide');
    var ev = flashTeamsJSON["events"][getEventJSONIndex(groupNum)];

    var cursor_x = cursor.attr("x1");
    ev.completed_x = cursor_x;

    // remove from either live or delayed tasks
    var idx = delayed_tasks.indexOf(groupNum);
    if (idx != -1) { // delayed task
        delayed_tasks.splice(idx, 1);
        completed_red_tasks.push(groupNum);
        //updateStatus(true);
        console.log("removed task from delayed and added to completed_red");
        sendEmailOnCompletionOfDelayedTask(groupNum);
    } else {
        idx = live_tasks.indexOf(groupNum);
        if (idx != -1){ // live task
            var task_g = getTaskGFromGroupNum (groupNum);
            var blue_width = drawBlueBox(ev, task_g);
            if (blue_width !== null){
                drawn_blue_tasks.push(groupNum);
                moveRemainingTasksLeft(blue_width);
                //updateStatus(true);
                sendEmailOnEarlyCompletion(blue_width);
            }
            live_tasks.splice(idx, 1);
        }
    }
    hidePopover(groupNum);

    // update db
    updateStatus(true);

    // reload status bar
    load_statusBar(status_bar_timeline_interval);*/
    //------------------------------//

};
<commit_msg>Modal closes on start task<commit_after>/* taskStatus.js
 * ---------------------------------------------
 * Handles status of the task ("started", "not_started", "delayed", "completed")
 * Formerly completeTask.js
 */

 //TASK STATUS COLORS
 var TASK_NOT_START_COLOR = "#C9C9C9";
 var TASK_START_COLOR = "blue";
 var TASK_DELAY_COLOR = "red";
 var TASK_COMPLETE_COLOR = "green";

//Fires on "Start" button on task modal
 function startTask(groupNum) {
    var indexOfJSON = getEventJSONIndex(groupNum);
    var eventObj = flashTeamsJSON["events"][indexOfJSON];
    eventObj.status = "started";

    //START TIMER
    //START HERE ALEXANDRA

    //Close the task modal
    $("#task_modal").modal('hide');

    updateStatus();
    drawEvent(eventObj); //Will update color
 }

//Alert firing on event complete buttons
function confirmCompleteTask(groupNum) {
    //Close the first (task) modal
    $("#task_modal").modal('hide');

    //Creates the alert modal title
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Have You Completed This Task?";

    //Gets information from event using id
    var indexOfJSON = getEventJSONIndex(groupNum);
    var events = flashTeamsJSON["events"];
    var eventToComplete = events[indexOfJSON];

    //Edits the confirmAction modal from _confirm_action.html.erb
    var alertText = document.getElementById("confirmActionText");
    alertText.innerHTML = completeTaskModalText(eventToComplete);

    //Code for the Task Completed Button
    var completeButton = document.getElementById("confirmButton");
    completeButton.innerHTML = "Task Completed";
    $("#confirmButton").attr("class","btn btn-success");
    if (eventToComplete.outputs != null && eventToComplete.outputs != "") {
        $("#confirmButton").prop('disabled', true); //Defaults to disabled
    }
    $('#confirmAction').modal('show');

    //Set change function on checkboxes, enable button if all checkboxes are checked
    $(".outputCheckbox").change(function() {
        var totalCheckboxes = $(".outputCheckbox").length;
        var checkedCheckboxes = $(".outputCheckbox:checked").length;
        if (totalCheckboxes == checkedCheckboxes) {
            $("#confirmButton").prop('disabled', false);
        } else {
            $("#confirmButton").prop('disabled', true);
        }
    });

    //Calls completeTask function if user confirms the complete
    document.getElementById("confirmButton").onclick=function(){
    	$('#confirmAction').modal('hide');
    	completeTask(groupNum);
    };
    hidePopover(groupNum);
}

//Return text to fill complete task modal
function completeTaskModalText(eventToComplete) {
    var modalText = "Outputs for " + eventToComplete["title"] + ":";

    //Get outputs from eventObj
    var eventOutputs = eventToComplete.outputs;
    if (eventOutputs != null && eventOutputs != "") {
        eventOutputs = eventToComplete.outputs.split(",");
    }

    //Create Checklist of outputs
    modalText += "<form id='event_checklist_" + eventToComplete.id + "' >";
    if (eventOutputs == null || eventOutputs == "") {
        modalText += "No outputs were specified for this task.";
    } else {
        for (i=0; i<eventOutputs.length; i++) {
            modalText += "<input type='checkbox' class='outputCheckbox'>" + eventOutputs[i] + "</input>
";
        }
    }
    modalText += "</form>";

    modalText+= "
Click 'Task Completed' to alert the PC and move on to the documentation questons."
    return modalText;
}

//Called when user confirms event completion alert
var completeTask = function(groupNum){
    //Update the status of a task
    var indexOfJSON = getEventJSONIndex(groupNum);
    var eventToComplete = flashTeamsJSON["events"][indexOfJSON];
    eventToComplete.status = "completed";

    //TODO: Iteration Marker - if we iterate and want to put it on the task, do it here

    //Update database, must be false b/c we are not using the old ticker
    updateStatus(false);
    drawEvent(eventToComplete);

    //Message the PC that the task has been completed
    //TODO

    //Guide worker to documentation questions
    //TODO

    //------------------------------//
    //OLD TICKER VERSION CODE, TO DELETE LATER, USE TO MAKE SURE NOT MISSING CASES??
    /*
    $('#confirmAction').modal('hide');
    var ev = flashTeamsJSON["events"][getEventJSONIndex(groupNum)];

    var cursor_x = cursor.attr("x1");
    ev.completed_x = cursor_x;

    // remove from either live or delayed tasks
    var idx = delayed_tasks.indexOf(groupNum);
    if (idx != -1) { // delayed task
        delayed_tasks.splice(idx, 1);
        completed_red_tasks.push(groupNum);
        //updateStatus(true);
        console.log("removed task from delayed and added to completed_red");
        sendEmailOnCompletionOfDelayedTask(groupNum);
    } else {
        idx = live_tasks.indexOf(groupNum);
        if (idx != -1){ // live task
            var task_g = getTaskGFromGroupNum (groupNum);
            var blue_width = drawBlueBox(ev, task_g);
            if (blue_width !== null){
                drawn_blue_tasks.push(groupNum);
                moveRemainingTasksLeft(blue_width);
                //updateStatus(true);
                sendEmailOnEarlyCompletion(blue_width);
            }
            live_tasks.splice(idx, 1);
        }
    }
    hidePopover(groupNum);

    // update db
    updateStatus(true);

    // reload status bar
    load_statusBar(status_bar_timeline_interval);*/
    //------------------------------//

};
<|endoftext|>