<commit_before>import React from "react";
import { Container } from "reactstrap";
import './styles.scss'
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'
const Remarkable = require('remarkable');

const md = new Remarkable();
md.set({
  breaks: true,
  linkify: true
});

const markdownSection1 = md.render("INSERT SECTION 1 HERE")
const markdownSection2 = md.render("INSERT SECTION 2 HERE")
const markdownSection3 = md.render("INSERT SECTION 3 HERE")
const markdownSection4 = md.render("INSERT SECTION 4 HERE")

const index = () => {
  return (
    <Container className="mt-5">

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline"/>

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" />

    </Container>

  );
};
<commit_msg>added export default index;<commit_after>import React from "react";
import { Container } from "reactstrap";
import './styles.scss'
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'
const Remarkable = require('remarkable');

const md = new Remarkable();
md.set({
  breaks: true,
  linkify: true
});

const markdownSection1 = md.render("INSERT SECTION 1 HERE")
const markdownSection2 = md.render("INSERT SECTION 2 HERE")
const markdownSection3 = md.render("INSERT SECTION 3 HERE")
const markdownSection4 = md.render("INSERT SECTION 4 HERE")

const index = () => {
  return (
    <Container className="mt-5">

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline"/>

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" />

    </Container>

  );
};

export default index;
<|endoftext|>


<commit_before>var mapApp = angular.module('mapApp', []);

mapApp.constant('ICONS', {
  RED: 'http://maps.google.com/mapfiles/ms/micons/red-dot.png',
  GREEN: 'http://maps.google.com/mapfiles/ms/micons/green-dot.png',
  BLUE: 'http://maps.google.com/mapfiles/ms/micons/blue-dot.png',
});

mapApp.controller('EventListCtrl', function($scope, $http, $interval, urls, mapSettings) {
  $scope.$location = window.location
  $scope.selectedEventsupport = {};
  $scope.initGoogleMap = function(rootElement) {

    var fullBounds = new google.maps.LatLngBounds();
    var params = {status: 'A'};
    $http.get(urls.events, {params: params}).success(function(data) {
        for (i in data.objects) {
            var event = data.objects[i];
            var lat=event.latest_location.latitude;
            var long=event.latest_location.longitude;
            var point=new google.maps.LatLng(lat, long);
        fullBounds.extend(point)
        };
    });

    var mapOptions = {
      zoom: 10,
      center: new google.maps.LatLng(50.444, 390.56),
      zoomControl: true,
      zoomControlOptions: {position: google.maps.ControlPosition.RIGHT_CENTER},
      panControl: true,
      panControlOptions: {position: google.maps.ControlPosition.RIGHT_TOP},
    };
    $scope.gmap = new google.maps.Map(rootElement, mapOptions);
    $scope.gwindow = new google.maps.InfoWindow({content: "Sup"});
    $scope.gwindow_opened = false;
    $scope.gmap.fitBounds(fullBounds);
  };
  $scope.zoomIn = function() {
    if ($scope.zoomedIn == false) {
      $scope.gmap.setZoom($scope.gmap.getZoom() + $scope.zoomScale);
      $scope.zoomedIn = true;
    }
  };
  $scope.zoomOut = function() {
    if ($scope.zoomedIn == true) {
      $scope.gmap.setZoom($scope.gmap.getZoom() - $scope.zoomScale);
      $scope.zoomedIn = false;
    }
  };
  $scope.select = function(event) {
    if (event == null) {
      $scope.zoomOut();
      $scope.selectedEvent = null;
      $scope.selectedEventsupport = {};
      window.location.hash = ''
    } else {
      var params = {event__id: event.id};
      $http.get(urls.eventupdates, {params: params}).success(function(data) {
      event.updates = data.objects;
      $scope.zoomIn();
      $scope.selectedEvent = event;
      window.location.hash = event.id
      $scope.selectedEvent.isNew = false;
      });
          for (i in $scope.events) {
              var event_support = $scope.events[i];
              if(event_support.type=="support"){
                  for (i in event_support.supported){
                    var support = event_support.supported[i]
                    if(support.id == event.id){
                      if ($scope.selectedEventsuppor == null){
                        $scope.selectedEventsupport[event_support.id] = event_support;
                      }else if ($scope.selectedEventsupport[event_support.id] == null){
                        $scope.selectedEventsupport[event_support.id] = event_support;
                      }
                    }
                  }
              }
            }
    };
  };
  $scope.update = function(highightNew, playSoundForNew) {
    var params = {status: 'A'};
    $http.get(urls.events, {params: params}).success(function(data) {
      var eventsAppeared = false, newEvents = {};
      for (i in data.objects) {
        var event = data.objects[i];
        newEvents[event.id] = event;
      }
      // Deleting old events
      for (oldEventId in $scope.events) {
        if (newEvents[oldEventId] == null) {
          delete $scope.events[oldEventId];
        }
      }
      // Adding new events
      for (newEventId in newEvents) {
        if ($scope.events[newEventId] == null) {
          var new_event =  newEvents[newEventId]
            if (highightNew){
              new_event.isNew = true
            } else {
              new_event.isNew = false
            }
          $scope.events[newEventId] = new_event;
          eventsAppeared = true;
        }
      }
      if ($scope.$location.hash!=""){
          var id = parseFloat($scope.$location.hash.split('#')[1])
          $scope.select( $scope.events[id])
        }
      if (eventsAppeared && playSoundForNew)
        document.getElementById('audiotag').play();
    });
  };
  $scope.focus = function(location) {
    $scope.gmap.panTo(new google.maps.LatLng(location.latitude,
                                             location.longitude));
  };

  $scope.updatePerSeconds = 5;
  $scope.selectedEvent = null;
  $scope.zoomedIn = false;
  $scope.zoomScale = 1;
  $scope.initGoogleMap(document.getElementById("map-canvas"));
  $scope.events = {};

  $scope.update(false, false);

  $interval(function() {
    $scope.update(mapSettings.highlight, mapSettings.sound);
  }, $scope.updatePerSeconds * 1000);
})
.factory('markerFactory', function() {
  return function(scope, element, content, icon, location, map, onclick) {
    var markerArgs = {
      icon: icon,
      position: new google.maps.LatLng(location.latitude, location.longitude),
    };

    var marker = new google.maps.Marker(markerArgs);
    marker.setMap(map);
    if (onclick)
      google.maps.event.addListener(marker, 'click', function() {
        scope.$eval(onclick);
      });

    if (content.length) {
      content = content.detach()[0];
    }
    var markersWindow = new google.maps.InfoWindow();

    google.maps.event.addListener(marker, 'mouseover', function() {
      markersWindow.setContent(content);
      markersWindow.open(map, marker);
    });
    google.maps.event.addListener(marker, 'mouseout', function() {
      if (markersWindow != null) markersWindow.close();
    });

    element.on('$destroy', function() {
      marker.setMap(null);
      marker = null;
      if (markersWindow != null) {
        markersWindow.close();
        markersWindow = null;
      }
    });

    return marker;
  };
})
.directive('eventMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    var location = scope.event.latest_location;

    if (location) {
      var map = scope.$parent.gmap;
      var icon = (scope.event.type == 'victim') ? ICONS.RED : ICONS.GREEN;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, icon, location,
                                 map, attrs.click);

      scope.$watch('event.isNew', function(isNew) {
        var animation = (isNew) ? google.maps.Animation.BOUNCE : null;
        marker.setAnimation(animation);
      });
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
})
.directive('supportMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    var location = scope.support.latest_location;

    if (location) {
      var map = scope.$parent.gmap;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, ICONS.GREEN, location,
                                 map, attrs.click);
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
})
.directive('eventupdateMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    if (scope.update.location != null) {
      var map = scope.$parent.gmap;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, ICONS.BLUE,
                                 scope.update.location, map);
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
});
<commit_msg>ticket:59 Fixed indentation & events focusing<commit_after>var mapApp = angular.module('mapApp', []);

mapApp.constant('ICONS', {
  RED: 'http://maps.google.com/mapfiles/ms/micons/red-dot.png',
  GREEN: 'http://maps.google.com/mapfiles/ms/micons/green-dot.png',
  BLUE: 'http://maps.google.com/mapfiles/ms/micons/blue-dot.png',
});

mapApp.controller('EventListCtrl', function($scope, $http, $interval, urls, mapSettings) {
  $scope.$location = window.location
  $scope.selectedEventsupport = {};
  $scope.initGoogleMap = function(rootElement) {

    var fullBounds = new google.maps.LatLngBounds();
    var params = {status: 'A'};
    $http.get(urls.events, {params: params}).success(function(data) {
      for (i in data.objects) {
        var event = data.objects[i];
        if (event.latest_location != null) {
          var point = new google.maps.LatLng(
            event.latest_location.latitude,
            event.latest_location.longitude
          );
          fullBounds.extend(point)
        }
      };
    });

    var mapOptions = {
      zoom: 10,
      center: new google.maps.LatLng(50.444, 390.56),
      zoomControl: true,
      zoomControlOptions: {position: google.maps.ControlPosition.RIGHT_CENTER},
      panControl: true,
      panControlOptions: {position: google.maps.ControlPosition.RIGHT_TOP},
    };
    $scope.gmap = new google.maps.Map(rootElement, mapOptions);
    $scope.gwindow = new google.maps.InfoWindow({content: "Sup"});
    $scope.gwindow_opened = false;
    $scope.gmap.fitBounds(fullBounds);
  };
  $scope.zoomIn = function() {
    if ($scope.zoomedIn == false) {
      $scope.gmap.setZoom($scope.gmap.getZoom() + $scope.zoomScale);
      $scope.zoomedIn = true;
    }
  };
  $scope.zoomOut = function() {
    if ($scope.zoomedIn == true) {
      $scope.gmap.setZoom($scope.gmap.getZoom() - $scope.zoomScale);
      $scope.zoomedIn = false;
    }
  };
  $scope.select = function(event) {
    if (event == null) {
      $scope.zoomOut();
      $scope.selectedEvent = null;
      $scope.selectedEventsupport = {};
      window.location.hash = ''
    } else {
      var params = {event__id: event.id};
      $http.get(urls.eventupdates, {params: params}).success(function(data) {
        event.updates = data.objects;
        $scope.zoomIn();
        $scope.selectedEvent = event;
        window.location.hash = event.id
        $scope.selectedEvent.isNew = false;
      });
      for (i in $scope.events) {
        var event_support = $scope.events[i];
        if(event_support.type=="support"){
          for (i in event_support.supported){
            var support = event_support.supported[i]
            if(support.id == event.id){
              if ($scope.selectedEventsuppor == null){
                $scope.selectedEventsupport[event_support.id] = event_support;
              }else if ($scope.selectedEventsupport[event_support.id] == null){
                $scope.selectedEventsupport[event_support.id] = event_support;
              }
            }
          }
        }
      }
    };
  };
  $scope.update = function(highightNew, playSoundForNew) {
    var params = {status: 'A'};
    $http.get(urls.events, {params: params}).success(function(data) {
      var eventsAppeared = false, newEvents = {};
      for (i in data.objects) {
        var event = data.objects[i];
        newEvents[event.id] = event;
      }
      // Deleting old events
      for (oldEventId in $scope.events) {
        if (newEvents[oldEventId] == null) {
          delete $scope.events[oldEventId];
        }
      }
      // Adding new events
      for (newEventId in newEvents) {
        if ($scope.events[newEventId] == null) {
          var new_event =  newEvents[newEventId]
            if (highightNew){
              new_event.isNew = true
            } else {
              new_event.isNew = false
            }
          $scope.events[newEventId] = new_event;
          eventsAppeared = true;
        }
      }
      if ($scope.$location.hash!=""){
          var id = parseFloat($scope.$location.hash.split('#')[1])
          $scope.select( $scope.events[id])
        }
      if (eventsAppeared && playSoundForNew)
        document.getElementById('audiotag').play();
    });
  };
  $scope.focus = function(location) {
    $scope.gmap.panTo(new google.maps.LatLng(location.latitude,
                                             location.longitude));
  };

  $scope.updatePerSeconds = 5;
  $scope.selectedEvent = null;
  $scope.zoomedIn = false;
  $scope.zoomScale = 1;
  $scope.initGoogleMap(document.getElementById("map-canvas"));
  $scope.events = {};

  $scope.update(false, false);

  $interval(function() {
    $scope.update(mapSettings.highlight, mapSettings.sound);
  }, $scope.updatePerSeconds * 1000);
})
.factory('markerFactory', function() {
  return function(scope, element, content, icon, location, map, onclick) {
    var markerArgs = {
      icon: icon,
      position: new google.maps.LatLng(location.latitude, location.longitude),
    };

    var marker = new google.maps.Marker(markerArgs);
    marker.setMap(map);
    if (onclick)
      google.maps.event.addListener(marker, 'click', function() {
        scope.$eval(onclick);
      });

    if (content.length) {
      content = content.detach()[0];
    }
    var markersWindow = new google.maps.InfoWindow();

    google.maps.event.addListener(marker, 'mouseover', function() {
      markersWindow.setContent(content);
      markersWindow.open(map, marker);
    });
    google.maps.event.addListener(marker, 'mouseout', function() {
      if (markersWindow != null) markersWindow.close();
    });

    element.on('$destroy', function() {
      marker.setMap(null);
      marker = null;
      if (markersWindow != null) {
        markersWindow.close();
        markersWindow = null;
      }
    });

    return marker;
  };
})
.directive('eventMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    var location = scope.event.latest_location;

    if (location) {
      var map = scope.$parent.gmap;
      var icon = (scope.event.type == 'victim') ? ICONS.RED : ICONS.GREEN;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, icon, location,
                                 map, attrs.click);

      scope.$watch('event.isNew', function(isNew) {
        var animation = (isNew) ? google.maps.Animation.BOUNCE : null;
        marker.setAnimation(animation);
      });
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
})
.directive('supportMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    var location = scope.support.latest_location;

    if (location) {
      var map = scope.$parent.gmap;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, ICONS.GREEN, location,
                                 map, attrs.click);
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
})
.directive('eventupdateMarker', function(markerFactory, ICONS) {
  var linker = function(scope, element, attrs) {
    if (scope.update.location != null) {
      var map = scope.$parent.gmap;
      var content = element.children().detach()[0];
      var marker = markerFactory(scope, element, content, ICONS.BLUE,
                                 scope.update.location, map);
    }
  };
  return {
    replace: true,
    template: '',
    restrict: 'E',
    link: linker,
  };
});
<|endoftext|>


<commit_before>var pg = require('pg');
var Q = require('q');

module.exports = PostgresAdapter;

var pgConfig;

var executeQuery = function (query, values, cb) {
  if (values && typeof values == 'function') {
    cb = values;
    values = undefined;
  }
  return Q.ninvoke(pg, 'connect', pgConfig)
    .then(function (client) {
      console.log(query);
      return Q.ninvoke(client, 'query', query, values);
    }).nend(cb);
};

function PostgresAdapter (tableName) {

  this.query = function (query, values, cb) {
    return executeQuery(query, values, cb);
  };

  this.all = function (cb) {
    var self = this;
    var query = 'SELECT * FROM ' + tableName;
    query += ' ORDER BY ' + self.prototype._primaryKey;
    return executeQuery(query)
      .then(function (result) {
        return result.rows.map(function (row) {
          return new self(row);
        });
      }).nend(cb);
  };

  this.findById = function (id, cb) {
    var self = this;
    var query = 'SELECT * FROM ' + tableName +
      ' WHERE ' + this.prototype._primaryKey + ' = $1;';
    return executeQuery(query, [id])
      .then(function (result) {
        if (result.rows.length > 0) {
          return new self(result.rows[0]);
        }
        else {
          return undefined;
        }
      });
  };

  this.insert = function (cb) {
    var self = this;
    var values = [];
    var query = 'INSERT INTO ' + tableName + '(';
    Object.keys(self._attributes).forEach(function (key, idx) {
      values.push(self._attributes[key]);
      if (idx != self._attributes.length - 1) {
        query += ',';
      }
      else {
        query += ')';
      }
    });
    query += 'VALUES(';
    values.forEach(function (val, idx) {
      query += '$'+idx;
      if (idx !== self._attributes.length - 1) {
        query += ',';
      }
      else {
        query += ')';
      }
    });
    return executeQuery(query, values, cb);
  };

  this.update = function (cb) {
    var self = this;
    var values = [];
    var query = 'UPDATE ' + tableName + ' SET ';
    Object.keys(self._attributes).forEach(function (key, idx) {
      values.push(self._attributes[key]);
      query += ' ' + key + ' = $' + values.length;
      if (idx !== self._attributes.length -1) {
        query += ',';
      }
    });
    values.push(this.id);
    query += ' WHERE ' + this._primaryKey + ' = $' + values.length + ';';
    return executeQuery(query, values, cb);
  };

  this.delete = function (cb) {
    var query = 'DELETE FROM ' + tableName + ' WHERE ' +
      this._primaryKey + ' = $1';
    return executeQuery(query, [this.id], cb);
  };

}

PostgresAdapter.configure = function (config) {
  pgConfig = config;
};

PostgresAdapter.addStatics = function (Model, adapter) {
  Model.query = adapter.query;
  Model.all = adapter.all;
  Model.findById = adapter.findById;
};

PostgresAdapter.addDelegates = function (Model, adapter) {
  Model.prototype.save = function () {
    if (this.id) {
      return adapter.update.call(this);
    }
    else {
      return adapter.insert.call(this);
    }

  };
  Model.prototype.delete = adapter.delete;
};

<commit_msg>fixing PG save queries, and adding RETURNING <id> to both (insert and update)<commit_after>var pg = require('pg');
var Q = require('q');

module.exports = PostgresAdapter;

var pgConfig;

var executeQuery = function (query, values, cb) {
  if (values && typeof values == 'function') {
    cb = values;
    values = undefined;
  }
  return Q.ninvoke(pg, 'connect', pgConfig)
    .then(function (client) {
      console.log(query);
      return Q.ninvoke(client, 'query', query, values);
    }).nend(cb);
};

function PostgresAdapter (tableName) {

  this.query = function (query, values, cb) {
    return executeQuery(query, values, cb);
  };

  this.all = function (cb) {
    var self = this;
    var query = 'SELECT * FROM ' + tableName;
    query += ' ORDER BY ' + self.prototype._primaryKey;
    return executeQuery(query)
      .then(function (result) {
        return result.rows.map(function (row) {
          return new self(row);
        });
      }).nend(cb);
  };

  this.findById = function (id, cb) {
    var self = this;
    var query = 'SELECT * FROM ' + tableName +
      ' WHERE ' + this.prototype._primaryKey + ' = $1;';
    return executeQuery(query, [id])
      .then(function (result) {
        if (result.rows.length > 0) {
          return new self(result.rows[0]);
        }
        else {
          return undefined;
        }
      });
  };

  this.insert = function (cb) {
    var self = this;
    var values = [];
    var query = 'INSERT INTO ' + tableName + '(';
    Object.keys(self._attributes).forEach(function (key, idx, keys) {
      values.push(self._attributes[key]);
      query += key;
      if (idx !== keys.length - 1) {
        query += ', ';
      }
      else {
        query += ')';
      }
    });
    query += ' VALUES(';
    values.forEach(function (val, idx) {
      var valId = idx + 1;
      query += '$' + valId;
      if (idx !== values.length - 1) {
        query += ', ';
      }
      else {
        query += ')';
      }
    });
    query += ' RETURNING ' + self._primaryKey;
    return executeQuery(query, values)
      .then(function (result) {
        return result.rows[0][self._primaryKey];
      }).nend(cb);
  };

  this.update = function (cb) {
    var self = this;
    var values = [];
    var query = 'UPDATE ' + tableName + ' SET ';
    Object.keys(self._attributes).forEach(function (key, idx, keys) {
      values.push(self._attributes[key]);
      query += ' ' + key + ' = $' + values.length;
      if (idx !== keys.length -1) {
        query += ',';
      }
    });
    values.push(this.id);
    query += ' WHERE ' + this._primaryKey + ' = $' + values.length;
    query += ' RETURNING ' + this._primaryKey;
    return executeQuery(query, values)
      .then(function (result) {
        return result.rows[0][self._primaryKey];
      }).nend(cb);
  };

  this.delete = function (cb) {
    var query = 'DELETE FROM ' + tableName + ' WHERE ' +
      this._primaryKey + ' = $1';
    return executeQuery(query, [this.id], cb);
  };

}

PostgresAdapter.configure = function (config) {
  pgConfig = config;
};

PostgresAdapter.addStatics = function (Model, adapter) {
  Model.query = adapter.query;
  Model.all = adapter.all;
  Model.findById = adapter.findById;
};

PostgresAdapter.addDelegates = function (Model, adapter) {
  Model.prototype.save = function () {
    if (this.id) {
      return adapter.update.call(this);
    }
    else {
      return adapter.insert.call(this);
    }
  };
  Model.prototype.delete = adapter.delete;
};

<|endoftext|>


<commit_before>// --------------------------------------------------------------------------------------------------------------------
//
// elb-config.js - config for AWS Elastic Load Balancing
//
// Copyright (c) 2011 AppsAttic Ltd - http://www.appsattic.com/
// Written by Andrew Chilton <chilts@appsattic.com>
//
// License: http://opensource.org/licenses/MIT
//
// --------------------------------------------------------------------------------------------------------------------

module.exports = {

    ApplySecurityGroupsToLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_ApplySecurityGroupsToLoadBalancer.html',
        defaults : {
            Action : 'ApplySecurityGroupsToLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            SecurityGroups : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    AttachLoadBalancerToSubnets : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_AttachLoadBalancerToSubnets.html',
        defaults : {
            Action : 'AttachLoadBalancerToSubnets'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Subnets : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    ConfigureHealthCheck : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_ConfigureHealthCheck.html',
        defaults : {
            Action : 'ConfigureHealthCheck'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            HealthyThreshold : {
                name     : 'Healthcheck.HealthyThreshold',
                required : true,
                type     : 'param',
            },
            Interval : {
                name     : 'Healthcheck.Interval',
                required : true,
                type     : 'param',
            },
            Target : {
                name     : 'Healthcheck.Target',
                required : true,
                type     : 'param',
            },
            Timeout : {
                name     : 'Healthcheck.Timeout',
                required : true,
                type     : 'param',
            },
            UnhealthyThreshold : {
                name     : 'Healthcheck.UnhealthyThreshold',
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateAppCookieStickinessPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateAppCookieStickinessPolicy.html',
        defaults : {
            Action : 'CreateAppCookieStickinessPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            CookieName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLBCookieStickinessPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLBCookieStickinessPolicy.html',
        defaults : {
            Action : 'CreateLBCookieStickinessPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            CookieExpirationPeriod : {
                required : false,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancer.html',
        defaults : {
            Action : 'CreateLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
            Listeners : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Listeners.member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            SecurityGroups : {
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
            Subnets : {
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    CreateLoadBalancerListeners : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancerListeners.html',
        defaults : {
            Action : 'CreateLoadBalancerListeners'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            Listeners : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Listeners.member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLoadBalancerPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancerPolicy.html',
        defaults : {
            Action : 'CreateLoadBalancerPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            Listeners : {
                // creates Listeners.member.1, Listeners.member.2, ...etc...
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyAttributes : {
                // wanted: AttributeName and AttributeValue for each object
                required : false,
                type     : 'param-array-of-objects',
                setName  : 'PolicyAttributes.member',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
            PolicyTypeName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeleteLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancer.html',
        defaults : {
            Action : 'DeleteLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeleteLoadBalancerListeners : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancerListeners.html',
        defaults : {
            Action : 'DeleteLoadBalancerListeners'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPorts : {
                required : true,
                type     : 'param-set',
                prefix   : 'member',
            },
        },
    },

    DeleteLoadBalancerPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancerPolicy.html',
        defaults : {
            Action : 'DeleteLoadBalancerPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeregisterInstancesFromLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeregisterInstancesFromLoadBalancer.html',
        defaults : {
            Action : 'DeregisterInstancesFromLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            // do an array-set instead of an array-of-objects (since it only has one item)
            Instances : {
                name     : 'InstanceId',
                required : true,
                type     : 'param-array-set',
                setName  : 'Instances.member',
            },
        },
    },

    DescribeInstanceHealth : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeInstanceHealth.html',
        defaults : {
            Action : 'DescribeInstanceHealth'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            // do an array-set instead of an array-of-objects (since it only has one item)
            Instances : {
                name     : 'InstanceId',
                required : false,
                type     : 'param-array-set',
                setName  : 'Instances.member',
            },
        },
    },

    DescribeLoadBalancerPolicies : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancerPolicies.html',
        defaults : {
            Action : 'DescribeLoadBalancerPolicies'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : false,
                type     : 'param',
            },
            PolicyNames : {
                required : false,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    DescribeLoadBalancerPolicyTypes : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancerPolicyTypes.html',
        defaults : {
            Action : 'DescribeLoadBalancerPolicyTypes'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            PolicyTypeNames : {
                required : false,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    DescribeLoadBalancers : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancers.html',
        defaults : {
            Action : 'DescribeLoadBalancers'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerNames : {
                // LoadBalancerNames.member.1, LoadBalancerNames.member.2, ...etc...
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
            Marker : {
                required : false,
                type     : 'param',
            },
        },
    },

    DetachLoadBalancersFromSubnets : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DetachLoadBalancerFromSubnets.html',
        defaults : {
            Action : 'DetachLoadBalancersFromSubnets'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Subnets : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    DisableAvailabilityZonesForLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DisableAvailabilityZonesForLoadBalancer.html',
        defaults : {
            Action : 'DisableAvailabilityZonesForLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    EnableAvailabilityZonesForLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_EnableAvailabilityZonesForLoadBalancer.html',
        defaults : {
            Action : 'EnableAvailabilityZonesForLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    RegisterInstancesWithLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_RegisterInstancesWithLoadBalancer.html',
        defaults : {
            Action : 'RegisterInstancesWithLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Instances : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Instances.member',
            },
        },
    },

    // check capitalisation
    SetLoadBalancerListenerSslCertificate : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerListenerSSLCertificate.html',
        defaults : {
            Action : 'SetLoadBalancerListenerSSLCertificate'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPort : {
                required : true,
                type     : 'param',
            },
            SslCertificateId : {
                name     : 'SSLCertificateId',
                required : true,
                type     : 'param',
            },
        },
    },

    SetLoadBalancerPoliciesForBackendServer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerPoliciesForBackendServer.html',
        defaults : {
            Action : 'SetLoadBalancerPoliciesForBackendServer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            InstancePort : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyNames : {
                required : true,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    SetLoadBalancerPoliciesOfListener : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerPoliciesOfListener.html',
        defaults : {
            Action : 'SetLoadBalancerPoliciesOfListener'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPort : {
                required : true,
                type     : 'param',
            },
            PolicyNames : {
                required : true,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

};

// --------------------------------------------------------------------------------------------------------------------
<commit_msg>ELB change<commit_after>// --------------------------------------------------------------------------------------------------------------------
//
// elb-config.js - config for AWS Elastic Load Balancing
//
// Copyright (c) 2011 AppsAttic Ltd - http://www.appsattic.com/
// Written by Andrew Chilton <chilts@appsattic.com>
//
// License: http://opensource.org/licenses/MIT
//
// --------------------------------------------------------------------------------------------------------------------

module.exports = {

    ApplySecurityGroupsToLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_ApplySecurityGroupsToLoadBalancer.html',
        defaults : {
            Action : 'ApplySecurityGroupsToLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            SecurityGroups : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    AttachLoadBalancerToSubnets : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_AttachLoadBalancerToSubnets.html',
        defaults : {
            Action : 'AttachLoadBalancerToSubnets'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Subnets : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    ConfigureHealthCheck : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_ConfigureHealthCheck.html',
        defaults : {
            Action : 'ConfigureHealthCheck'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            HealthyThreshold : {
                name     : 'Healthcheck.HealthyThreshold',
                required : true,
                type     : 'param',
            },
            Interval : {
                name     : 'Healthcheck.Interval',
                required : true,
                type     : 'param',
            },
            Target : {
                name     : 'Healthcheck.Target',
                required : true,
                type     : 'param',
            },
            Timeout : {
                name     : 'Healthcheck.Timeout',
                required : true,
                type     : 'param',
            },
            UnhealthyThreshold : {
                name     : 'Healthcheck.UnhealthyThreshold',
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateAppCookieStickinessPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateAppCookieStickinessPolicy.html',
        defaults : {
            Action : 'CreateAppCookieStickinessPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            CookieName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLBCookieStickinessPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLBCookieStickinessPolicy.html',
        defaults : {
            Action : 'CreateLBCookieStickinessPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            CookieExpirationPeriod : {
                required : false,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancer.html',
        defaults : {
            Action : 'CreateLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
            Listeners : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Listeners.member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            SecurityGroups : {
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
            Subnets : {
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    CreateLoadBalancerListeners : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancerListeners.html',
        defaults : {
            Action : 'CreateLoadBalancerListeners'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            Listeners : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Listeners.member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    CreateLoadBalancerPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_CreateLoadBalancerPolicy.html',
        defaults : {
            Action : 'CreateLoadBalancerPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            Listeners : {
                // creates Listeners.member.1, Listeners.member.2, ...etc...
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyAttributes : {
                // wanted: AttributeName and AttributeValue for each object
                required : false,
                type     : 'param-array-of-objects',
                setName  : 'PolicyAttributes.member',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
            PolicyTypeName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeleteLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancer.html',
        defaults : {
            Action : 'DeleteLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeleteLoadBalancerListeners : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancerListeners.html',
        defaults : {
            Action : 'DeleteLoadBalancerListeners'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPorts : {
                required : true,
                type     : 'param-set',
                prefix   : 'member',
            },
        },
    },

    DeleteLoadBalancerPolicy : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeleteLoadBalancerPolicy.html',
        defaults : {
            Action : 'DeleteLoadBalancerPolicy'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyName : {
                required : true,
                type     : 'param',
            },
        },
    },

    DeregisterInstancesFromLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DeregisterInstancesFromLoadBalancer.html',
        defaults : {
            Action : 'DeregisterInstancesFromLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Instances : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Instances.member',
            },
        },
    },

    DescribeInstanceHealth : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeInstanceHealth.html',
        defaults : {
            Action : 'DescribeInstanceHealth'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Instances : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Instances.member',
            },
        },
    },

    DescribeLoadBalancerPolicies : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancerPolicies.html',
        defaults : {
            Action : 'DescribeLoadBalancerPolicies'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : false,
                type     : 'param',
            },
            PolicyNames : {
                required : false,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    DescribeLoadBalancerPolicyTypes : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancerPolicyTypes.html',
        defaults : {
            Action : 'DescribeLoadBalancerPolicyTypes'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            PolicyTypeNames : {
                required : false,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    DescribeLoadBalancers : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DescribeLoadBalancers.html',
        defaults : {
            Action : 'DescribeLoadBalancers'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerNames : {
                // LoadBalancerNames.member.1, LoadBalancerNames.member.2, ...etc...
                required : false,
                type     : 'param-array',
                prefix   : 'member',
            },
            Marker : {
                required : false,
                type     : 'param',
            },
        },
    },

    DetachLoadBalancersFromSubnets : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DetachLoadBalancerFromSubnets.html',
        defaults : {
            Action : 'DetachLoadBalancersFromSubnets'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Subnets : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    DisableAvailabilityZonesForLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_DisableAvailabilityZonesForLoadBalancer.html',
        defaults : {
            Action : 'DisableAvailabilityZonesForLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    EnableAvailabilityZonesForLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_EnableAvailabilityZonesForLoadBalancer.html',
        defaults : {
            Action : 'EnableAvailabilityZonesForLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            AvailabilityZones : {
                required : true,
                type     : 'param-array',
                prefix   : 'member',
            },
        },
    },

    RegisterInstancesWithLoadBalancer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_RegisterInstancesWithLoadBalancer.html',
        defaults : {
            Action : 'RegisterInstancesWithLoadBalancer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            Instances : {
                required : true,
                type     : 'param-array-of-objects',
                setName  : 'Instances.member',
            },
        },
    },

    // check capitalisation
    SetLoadBalancerListenerSslCertificate : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerListenerSSLCertificate.html',
        defaults : {
            Action : 'SetLoadBalancerListenerSSLCertificate'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPort : {
                required : true,
                type     : 'param',
            },
            SslCertificateId : {
                name     : 'SSLCertificateId',
                required : true,
                type     : 'param',
            },
        },
    },

    SetLoadBalancerPoliciesForBackendServer : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerPoliciesForBackendServer.html',
        defaults : {
            Action : 'SetLoadBalancerPoliciesForBackendServer'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            InstancePort : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            PolicyNames : {
                required : true,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

    SetLoadBalancerPoliciesOfListener : {
        url : 'http://docs.amazonwebservices.com/ElasticLoadBalancing/latest/APIReference/API_SetLoadBalancerPoliciesOfListener.html',
        defaults : {
            Action : 'SetLoadBalancerPoliciesOfListener'
        },
        args : {
            Action : {
                required : true,
                type     : 'param',
            },
            LoadBalancerName : {
                required : true,
                type     : 'param',
            },
            LoadBalancerPort : {
                required : true,
                type     : 'param',
            },
            PolicyNames : {
                required : true,
                type     : 'param-array',
                prefix   : 'member'
            },
        },
    },

};

// --------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*!
 * API для организации микрошаблонов внутри директивы
 */

/**
 * Разбить строку по пробелам и вернуть массив
 * (учитываются директивы)
 *
 * @param {string} str - исходная строка
 * @return {!Array}
 */
function splitBySpace(str) {
	var escape = false;
	var res = [''],
		bOpen = 0,
		bStart = false;

	for (let i = -1; ++i < str.length;) {
		let currentEscape = escape;
		let el = str.charAt(i),
			part = str.substr(i, includeDirLength);

		if (el === '\\' || escape) {
			escape = !escape;
		}

		if (!currentEscape && includeDirMap[part]) {
			i += includeDirLength - 1;
			res[res.length - 1] += part;

			bStart = true;
			bOpen++;

			continue;
		}

		if (bStart) {
			if (el === LEFT_BLOCK) {
				bOpen++;

			} else if (el === RIGHT_BLOCK) {
				bOpen--;
			}
		}

		if (el === ' ' && !bOpen) {
			res.push('');
		}

		if (el !== ' ' || bOpen) {
			res[res.length - 1] += el;
		}
	}

	return res;
}

/**
 * Заменить ${ ... } или #{ ... } в указанной строке на значение вывода
 *
 * @param {string} str - исходная строка
 * @param {?boolean=} [opt_sys=false] - если true, то запуск функции считается системным вызовом
 * @param {?boolean=} [opt_replace=false] - если true, то директивы экранируются (заменяются на __SNAKESKIN__\d+_)
 * @return {string}
 */
DirObj.prototype.replaceTplVars = function (str, opt_sys, opt_replace) {
	str = this.pasteDangerBlocks(str);

	var start = 0;
	var begin = 0,
		dir = '',
		res = '';

	var escape = false,
		comment = false;

	var bOpen = false,
		bEnd = true,
		bEscape = false;

	var part = '',
		rPart = '';

	var nextLineMap = {
		'n': '\n',
		'r': '\r'
	};

	for (let i = -1; ++i < str.length;) {
		let currentEscape = escape,
			pos = i;

		let el = str.charAt(i),
			next = str.charAt(i + 1);

		if (str.substr(i, 2) === '\r\n') {
			continue;
		}

		if (begin) {
			if (!bOpen) {
				if ((el === '\\' && strongSysEscapeMap[next]) || escape) {
					escape = !escape;
				}

				if (escape) {
					continue;
				}

				if (el === '\\' && nextLineMap[next]) {
					el = nextLineMap[next];
					i++;
				}

				// Обработка комментариев
				if (!currentEscape) {
					let commentType = returnComment(str, pos);

					if (commentType) {
						if (!comment) {
							comment = commentType;
							i += commentType.length - 1;

						} else if (commentType === MULT_COMMENT_END && comment === MULT_COMMENT_START) {
							comment = false;
							i += commentType.length - 1;
							continue;
						}

					} else if (nextLineRgxp.test(el) && comment === SINGLE_COMMENT) {
						comment = false;
					}
				}

				if (comment) {
					continue;
				}

				if (escapeEndMap[el] || escapeEndWords[rPart]) {
					bEnd = true;

				} else if (bEndRgxp.test(el)) {
					bEnd = false;
				}

				if (partRgxp.test(el)) {
					part += el;

				} else {
					rPart = part;
					part = '';
				}

				if (el === LEFT_BLOCK) {
					begin++;

				} else if (el === RIGHT_BLOCK) {
					begin--;
				}
			}

			if (escapeMap[el] && (el !== '/' || bEnd) && !bOpen) {
				bOpen = el;

			} else if (bOpen && (el === '\\' || bEscape)) {
				bEscape = !bEscape;

			} else if (escapeMap[el] && bOpen === el && !bEscape) {
				bOpen = false;
				bEnd = false;
			}

			if (begin) {
				dir += el;

			} else {
				escape = false;

				let tmp = '\' + ' +
					this.prepareOutput(this.replaceDangerBlocks(dir).trim() || '\'\'', opt_sys) +
					' + \'';

				if (opt_replace) {
					res += `__SNAKESKIN__${this.dirContent.length}_`;
					this.dirContent.push(tmp);

				} else {
					res += tmp;
				}
			}

		} else {
			if (el === '\\' && includeSysEscapeMap[next] || escape) {
				escape = !escape;
			}

			if (escape) {
				continue;
			}

			if (!currentEscape && includeDirMap[str.substr(pos, includeDirLength)]) {
				begin++;
				dir = '';

				start = i;
				i += includeDirLength - 1;

				escape = false;
				continue;
			}

			res += el !== '\\' || currentEscape ?
				applyDefEscape(el) : escapeSingleQuote(el);
		}
	}

	return res;
};
<commit_msg>Refactoring<commit_after>/*!
 * API для организации микрошаблонов внутри директивы
 */

/**
 * Разбить строку по пробелам и вернуть массив
 * (учитываются директивы)
 *
 * @param {string} str - исходная строка
 * @return {!Array}
 */
function splitBySpace(str) {
	const
		res = [''];

	let
		escape = false,
		bOpen = 0,
		bStart = false;

	for (let i = -1; ++i < str.length;) {
		const
			currentEscape = escape,
			el = str.charAt(i),
			part = str.substr(i, includeDirLength);

		if (el === '\\' || escape) {
			escape = !escape;
		}

		if (!currentEscape && includeDirMap[part]) {
			i += includeDirLength - 1;
			res[res.length - 1] += part;

			bStart = true;
			bOpen++;

			continue;
		}

		if (bStart) {
			if (el === LEFT_BLOCK) {
				bOpen++;

			} else if (el === RIGHT_BLOCK) {
				bOpen--;
			}
		}

		if (el === ' ' && !bOpen) {
			res.push('');
		}

		if (el !== ' ' || bOpen) {
			res[res.length - 1] += el;
		}
	}

	return res;
}

/**
 * Заменить ${ ... } или #{ ... } в указанной строке на значение вывода
 *
 * @param {string} str - исходная строка
 * @param {?boolean=} [opt_sys=false] - если true, то запуск функции считается системным вызовом
 * @param {?boolean=} [opt_replace=false] - если true, то директивы экранируются (заменяются на __SNAKESKIN__\d+_)
 * @return {string}
 */
DirObj.prototype.replaceTplVars = function (str, opt_sys, opt_replace) {
	str = this.pasteDangerBlocks(str);

	let
		start = 0,
		begin = 0,
		dir = '',
		res = '';

	let
		escape = false,
		comment = false;

	let
		bOpen = false,
		bEnd = true,
		bEscape = false;

	let
		part = '',
		rPart = '';

	const nextLineMap = {
		'n': '\n',
		'r': '\r'
	};

	for (let i = -1; ++i < str.length;) {
		const
			currentEscape = escape,
			pos = i;

		let
			el = str.charAt(i),
			next = str.charAt(i + 1);

		if (str.substr(i, 2) === '\r\n') {
			continue;
		}

		if (begin) {
			if (!bOpen) {
				if ((el === '\\' && strongSysEscapeMap[next]) || escape) {
					escape = !escape;
				}

				if (escape) {
					continue;
				}

				if (el === '\\' && nextLineMap[next]) {
					el = nextLineMap[next];
					i++;
				}

				// Обработка комментариев
				if (!currentEscape) {
					let commentType = returnComment(str, pos);

					if (commentType) {
						if (!comment) {
							comment = commentType;
							i += commentType.length - 1;

						} else if (commentType === MULT_COMMENT_END && comment === MULT_COMMENT_START) {
							comment = false;
							i += commentType.length - 1;
							continue;
						}

					} else if (nextLineRgxp.test(el) && comment === SINGLE_COMMENT) {
						comment = false;
					}
				}

				if (comment) {
					continue;
				}

				if (escapeEndMap[el] || escapeEndWords[rPart]) {
					bEnd = true;

				} else if (bEndRgxp.test(el)) {
					bEnd = false;
				}

				if (partRgxp.test(el)) {
					part += el;

				} else {
					rPart = part;
					part = '';
				}

				if (el === LEFT_BLOCK) {
					begin++;

				} else if (el === RIGHT_BLOCK) {
					begin--;
				}
			}

			if (escapeMap[el] && (el !== '/' || bEnd) && !bOpen) {
				bOpen = el;

			} else if (bOpen && (el === '\\' || bEscape)) {
				bEscape = !bEscape;

			} else if (escapeMap[el] && bOpen === el && !bEscape) {
				bOpen = false;
				bEnd = false;
			}

			if (begin) {
				dir += el;

			} else {
				escape = false;

				let tmp = '\' + ' +
					this.prepareOutput(this.replaceDangerBlocks(dir).trim() || '\'\'', opt_sys) +
					' + \'';

				if (opt_replace) {
					res += `__SNAKESKIN__${this.dirContent.length}_`;
					this.dirContent.push(tmp);

				} else {
					res += tmp;
				}
			}

		} else {
			if (el === '\\' && includeSysEscapeMap[next] || escape) {
				escape = !escape;
			}

			if (escape) {
				continue;
			}

			if (!currentEscape && includeDirMap[str.substr(pos, includeDirLength)]) {
				begin++;
				dir = '';

				start = i;
				i += includeDirLength - 1;

				escape = false;
				continue;
			}

			res += el !== '\\' || currentEscape ?
				applyDefEscape(el) : escapeSingleQuote(el);
		}
	}

	return res;
};
<|endoftext|>


<commit_before>define(['./util', './Rarity', './Level', './Card'], function define__cardcollection(util, Rarity, Level, Card) {

    function CardNotFound() {}
    CardNotFound.prototype = Error;

    function identity(x) { return !!x; }

    /**
     * @param {CardCollection} cardList
     * @param card
     * @returns {{standard: boolean, deck: boolean, combo: boolean, farmable: string}}
     */
    function categorize_card(cardList, card) {
        var standard = card.set < 5000 || 7000 === card.set;
        var deck = standard && !card.commander && !card.is_combo && !card.is_defense && !card.hidden;
        var combo = 1 === card.levels.length && !!card.attack_multiplier;

        return {
            "standard": standard,
            "deck": deck,
            "combo": combo,
            "f2p": 1 === card.set,
            "item": cardList.isItem(card),
            "precombo": !!card.combo_card_id,
            "hidden": card.hidden,
            "card": card
        }
    }

    function flatten_card_category(cardCategory) {
        return cardCategory.card;
    }

    function upgrade_card(card, level) {
        card = util.clone(card);

        level = new Level(level, new Rarity(card.rarity));

        var upgrade = card.levels[level.getAbsoluteValue() - 1];
        if (!upgrade) {
            throw new Error('„' + card.name + '” doesn’t have this level: ' + level.getAbsoluteValue());
        }

        card.attack = upgrade.attack;
        card.health = upgrade.health;
        card.skills = upgrade.skills;

        card.level = level.getValue();
        card.fuse = level.getFuse();

        return card;
    }

    function combo_value(alpha, bravo, multiplier) {
        return Math.max(alpha, bravo, Math.ceil(1.1 * (alpha + bravo) * multiplier));
    }

    function hydrate_combo(characterLevel, itemLevel, combo) {
        if (2 === arguments.length) {
            combo = arguments[1];
            itemLevel = characterLevel = arguments[0];
        } else if (1 === arguments.length) {
            combo = arguments[0];
            characterLevel = itemLevel = "1";
        }

        try {
            var character = upgrade_card(this.get(combo.character), characterLevel || "1");
            var item = upgrade_card(this.get(combo.item), itemLevel || "1");
            var result = util.clone(this.get(combo.card_id));
        } catch (E) {
            if (E.constructor.name = CardNotFound.name) {
                return null;
            }

            throw E;
        }

        result.rarity = Math.ceil(character.rarity /2 + item.rarity /2);
        result.health = combo_value(item.health, character.health, result.health_multiplier);
        result.attack = combo_value(item.attack, character.attack, result.attack_multiplier);

        result.power = 1.1 * (3 * character.attack + 3 * item.attack + character.health + item.health);

        result.is_combo = true;

        result.skills = Object.keys(result.skills).reduce(function (skills, key) {
            skills[key] = {
                x: Math.floor((result.skills[key].v-1) * (result.power - result.skills[key].p) / (100 - result.skills[key].p) +1),
                y: result.skills[key].y
            };

            return skills;
        }, {});

        return {
            "character": character,
            "item": item,
            "result": addLevels(result, []) // recalculate first level
        }
    }

    function parseCombo(combo) {
        var character = parseInt(combo.querySelector('cards').getAttribute('card1'));
        var item = parseInt(combo.querySelector('cards').getAttribute('card2'));

        return {
            "id": [character, item].sort().join("~"),
            "card_id": parseInt(combo.querySelector('card_id').textContent),
            "character": character,
            "item": item
        }
    }

    function releaseDate(combo) {
        var startTime = combo.querySelector('start_time') || {"textContent":0};

        return (new Date) / 1000 > startTime.textContent;
    }

    function addLevels(unit, upgrades) {
        unit.levels = [{
            "health": unit.health,
            "attack": unit.attack,
            "skills": unit.skills
        }];

        upgrades.reduce(function(values, upgrade) {
            values = addSkills(util.clone(values), [].slice.apply(upgrade.querySelectorAll('skill')));

            values.attack = parseInt((upgrade.querySelector('attack') || { 'textContent': values.attack }).textContent);
            values.health = parseInt((upgrade.querySelector('health') || { 'textContent': values.health }).textContent);

            unit.levels.push(values);

            return values;
        }, unit.levels[0]);

        return unit;
    }

    function addSkills(unit, skills) {
        unit.skills = unit.skills || {};

        skills.forEach(function (e) {
            unit.skills[e.getAttribute('id')] = {
                "p": parseInt(e.getAttribute('p')) || null,
                "x": parseInt(e.getAttribute('x')) || null,
                "v": parseInt(e.getAttribute('v')) || null,
                "y": e.getAttribute('y') || null
            };
        });

        return unit;
    }

    function normalizePicture(picture, type) {
        return ['FG', 'AD', 'BB', 'KH', 'FT', 'generic'][parseInt(type)-1]
            + "_" + picture.replace(/^(fg|koth|ad|bb|ft|kh|fr|generic)_/i, '');
    }

    function parseUnit(unit) {
        function v(name) {
            return (unit.querySelector(name) || {}).textContent;
        }

        var rarity = parseInt(v('rarity'));
        var name = (5 === rarity ? "Mythic " : "") + v('name');

        return addLevels(addSkills({
            id: parseInt(v('id')),
            name: name,
            slug: util.slugify(name),
            desc: v('desc'),
            picture: normalizePicture(v('picture'), v('type')),
            commander: !!v('commander'),
            is_combo: !!parseFloat(v("attack_multiplier")),
            is_defense: !!v('defense_card_id'),
            rarity: rarity,
            trait: v('trait'),
            set: parseInt(v('set')),
            type: parseInt(v('type')),
            hidden: !!v('hidden'),
            combo_card_id: parseInt(v("combo_card_id")) || null,
            health: parseInt(v('health')) || 0,
            attack: parseInt(v('attack')) || 0,
            health_multiplier: parseFloat(v('health_multiplier')) || 0,
            attack_multiplier: parseFloat(v('attack_multiplier')) || 0
        }, [].slice.apply(unit.querySelectorAll('unit > skill'))), [].slice.apply(unit.querySelectorAll('upgrade')));
    }

    function CardCollection(listResponseXML) {
        this.defaultInclude = ['deck'];

        listResponseXML = listResponseXML.map(function (responseXML) {
            return (new DOMParser).parseFromString(responseXML, 'application/xml');
        });

        this.items = listResponseXML.reduce(function (collection, xml) {
            return collection.concat([].slice.apply(xml.querySelectorAll('unit')).map(parseUnit));
        }, []);

        this.combos = listResponseXML.reduce(function (collection, xml) {
            return collection.concat(
                [].slice.apply(xml.querySelectorAll('combo'))
                    .filter(releaseDate)
                    .map(parseCombo)
            );
        }, []);

        this.farmable = listResponseXML.reduce(function (farmable, xml) {
            return [].slice.apply(xml.querySelectorAll('rewards card')).reduce(function(farmable, card) {
                if (parseInt(card.parentNode.parentNode.querySelector('id').textContent) > 1000) {
                    return farmable;
                }

                farmable[card.getAttribute('id')] = true;

                return farmable;
            }, farmable);
        }, {});

        this.types = {
            "characters": this.combos.map(function (combo) { return combo.character; }),
            "items": this.combos.map(function (combo) { return combo.item; })
        }
    }

    CardCollection.prototype.COMBO_ROLE_CHARACTER = 'character';
    CardCollection.prototype.COMBO_ROLE_ITEM = 'item';
    CardCollection.prototype.COMBO_ROLE_PRECOMBO = 'precombo';

    CardCollection.prototype.getCards = function cardcollection__getCards(include) {
        include = include || this.defaultInclude;
        return this.items.map(categorize_card.bind(null, this))
            .filter(function (item) {
                return include.reduce(function (result, key) {
                    var exclude = "-" === key[0];
                    key = key.replace(/^[+-]/, '');

                    return exclude ? (result && ! item[key]) : (result || item[key]);
                }, false);
            }).map(flatten_card_category);
    };

    CardCollection.prototype.getComboRole = function cardcollection__getComboRole(card) {
        return -1 !== this.types.characters.indexOf(card.id) ? this.COMBO_ROLE_CHARACTER
            : -1 !== this.types.items.indexOf(card.id) ? this.COMBO_ROLE_ITEM
            : this.COMBO_ROLE_PRECOMBO;
    };

    CardCollection.prototype.isPrecombo = function cardcollection__isPrecombo(card) {
        return this.COMBO_ROLE_PRECOMBO === this.getComboRole(card);
    };

    CardCollection.prototype.isItem = function cardcollection__isItem(card) {
        return this.COMBO_ROLE_ITEM === this.getComboRole(card);
    };

    CardCollection.prototype.find = function cardcollection__find(options) {
        if ("string" === typeof options) {
            options = { "name": options }
        }

        var name = util.slugify(options.name);
        var include = options.include || this.defaultInclude;

        return this.items.filter(function (card) {
            return name === card.slug;
        }).map(categorize_card.bind(null, this)).sort(function (alpha, bravo) {
            return include.reduce(function (result, key) {
                var dir = "-" === key[0] ? -1 : 1;
                key = key.replace(/^[+-]/, '');

                return result || (bravo[key] - alpha[key]) * dir;
            }, 0);
        }).map(flatten_card_category)[0];
    };

    CardCollection.prototype.get = function cardcollection_(id, optional) {
        for (var i = 0, card; card = this.items[i]; i++) {
            if (id === card.id) {
                return card;
            }
        }

        if (optional) {
            return null;
        }

        throw new CardNotFound;
    };

    CardCollection.forLevel = CardCollection.prototype.forLevel = function cardcollection__forLevel(card, level) {
        card = upgrade_card(card, level);

        return new Card({
            id: card.id,
            name: card.name,
            image: card.picture,
            rarity: card.rarity,
            attack: card.attack,
            health: card.health,
            level: card.level,
            trait: card.trait,
            fuse: card.fuse,
            is_combo: card.is_combo,
            skills: Object.keys(card.skills).map(function (skill) {
                return {
                    type: skill,
                    value: Math.abs(card.skills[skill].x),
                    target: card.skills[skill].y ? (/\d/.test(card.skills[skill].y) ? "show" : "trait") : null
                };
            })
        });
    };

    CardCollection.prototype.getHydratedCombos = function cardcollection__getHydratedCombos(characterLevel, itemLevel) {
        return this.combos.map(hydrate_combo.bind(this, characterLevel, itemLevel)).filter(identity);
    };

    CardCollection.prototype.getCombo = function cardcollection__getCombo(alpha, bravo) {
        for (var i = 0, combo; combo = this.combos[i]; i++) {
            if (combo.character === alpha.id && combo.item === bravo.id) {
                return hydrate_combo.call(this, alpha.getLevelString(), bravo.getLevelString(), combo);
            } else if (combo.character === bravo.id && combo.item === alpha.id) {
                return hydrate_combo.call(this, bravo.getLevelString(), alpha.getLevelString(), combo);
            }
        }

        return null;
    };

    CardCollection.prototype.getRecipesIncluding = function cardcollection__getRecipesIncluding(card, level) {
        return this.combos.filter(function (combo) {
            return !!~[combo.card_id, combo.character, combo.item].indexOf(card.id);
        }).map(hydrate_combo.bind(this, level, level)).filter(identity);
    };

    return CardCollection;

});
<commit_msg>ignore erronous combo xml<commit_after>define(['./util', './Rarity', './Level', './Card'], function define__cardcollection(util, Rarity, Level, Card) {

    function CardNotFound() {}
    CardNotFound.prototype = Error;

    function identity(x) { return !!x; }

    /**
     * @param {CardCollection} cardList
     * @param card
     * @returns {{standard: boolean, deck: boolean, combo: boolean, farmable: string}}
     */
    function categorize_card(cardList, card) {
        var standard = card.set < 5000 || 7000 === card.set;
        var deck = standard && !card.commander && !card.is_combo && !card.is_defense && !card.hidden;
        var combo = 1 === card.levels.length && !!card.attack_multiplier;

        return {
            "standard": standard,
            "deck": deck,
            "combo": combo,
            "f2p": 1 === card.set,
            "item": cardList.isItem(card),
            "precombo": !!card.combo_card_id,
            "hidden": card.hidden,
            "card": card
        }
    }

    function flatten_card_category(cardCategory) {
        return cardCategory.card;
    }

    function upgrade_card(card, level) {
        card = util.clone(card);

        level = new Level(level, new Rarity(card.rarity));

        var upgrade = card.levels[level.getAbsoluteValue() - 1];
        if (!upgrade) {
            throw new Error('„' + card.name + '” doesn’t have this level: ' + level.getAbsoluteValue());
        }

        card.attack = upgrade.attack;
        card.health = upgrade.health;
        card.skills = upgrade.skills;

        card.level = level.getValue();
        card.fuse = level.getFuse();

        return card;
    }

    function combo_value(alpha, bravo, multiplier) {
        return Math.max(alpha, bravo, Math.ceil(1.1 * (alpha + bravo) * multiplier));
    }

    function hydrate_combo(characterLevel, itemLevel, combo) {
        if (2 === arguments.length) {
            combo = arguments[1];
            itemLevel = characterLevel = arguments[0];
        } else if (1 === arguments.length) {
            combo = arguments[0];
            characterLevel = itemLevel = "1";
        }

        try {
            var character = upgrade_card(this.get(combo.character), characterLevel || "1");
            var item = upgrade_card(this.get(combo.item), itemLevel || "1");
            var result = util.clone(this.get(combo.card_id));
        } catch (E) {
            if (E.constructor.name = CardNotFound.name) {
                return null;
            }

            throw E;
        }

        result.rarity = Math.ceil(character.rarity /2 + item.rarity /2);
        result.health = combo_value(item.health, character.health, result.health_multiplier);
        result.attack = combo_value(item.attack, character.attack, result.attack_multiplier);

        result.power = 1.1 * (3 * character.attack + 3 * item.attack + character.health + item.health);

        result.is_combo = true;

        result.skills = Object.keys(result.skills).reduce(function (skills, key) {
            skills[key] = {
                x: Math.floor((result.skills[key].v-1) * (result.power - result.skills[key].p) / (100 - result.skills[key].p) +1),
                y: result.skills[key].y
            };

            return skills;
        }, {});

        return {
            "character": character,
            "item": item,
            "result": addLevels(result, []) // recalculate first level
        }
    }

    function parseCombo(combo) {
        var character = parseInt(combo.querySelector('cards').getAttribute('card1'));
        var item = parseInt(combo.querySelector('cards').getAttribute('card2'));

        return {
            "id": [character, item].sort().join("~"),
            "card_id": parseInt(combo.querySelector('card_id').textContent),
            "character": character,
            "item": item
        }
    }

    function validate_combo(combo) {
        var card = combo.querySelector('cards');

        return false === isNaN(parseInt(card.getAttribute('card1')))
            && false === isNaN(parseInt(card.getAttribute('card2')));
    }

    function releaseDate(combo) {
        var startTime = combo.querySelector('start_time') || {"textContent":0};

        return (new Date) / 1000 > startTime.textContent;
    }

    function addLevels(unit, upgrades) {
        unit.levels = [{
            "health": unit.health,
            "attack": unit.attack,
            "skills": unit.skills
        }];

        upgrades.reduce(function(values, upgrade) {
            values = addSkills(util.clone(values), [].slice.apply(upgrade.querySelectorAll('skill')));

            values.attack = parseInt((upgrade.querySelector('attack') || { 'textContent': values.attack }).textContent);
            values.health = parseInt((upgrade.querySelector('health') || { 'textContent': values.health }).textContent);

            unit.levels.push(values);

            return values;
        }, unit.levels[0]);

        return unit;
    }

    function addSkills(unit, skills) {
        unit.skills = unit.skills || {};

        skills.forEach(function (e) {
            unit.skills[e.getAttribute('id')] = {
                "p": parseInt(e.getAttribute('p')) || null,
                "x": parseInt(e.getAttribute('x')) || null,
                "v": parseInt(e.getAttribute('v')) || null,
                "y": e.getAttribute('y') || null
            };
        });

        return unit;
    }

    function normalizePicture(picture, type) {
        return ['FG', 'AD', 'BB', 'KH', 'FT', 'generic'][parseInt(type)-1]
            + "_" + picture.replace(/^(fg|koth|ad|bb|ft|kh|fr|generic)_/i, '');
    }

    function parseUnit(unit) {
        function v(name) {
            return (unit.querySelector(name) || {}).textContent;
        }

        var rarity = parseInt(v('rarity'));
        var name = (5 === rarity ? "Mythic " : "") + v('name');

        return addLevels(addSkills({
            id: parseInt(v('id')),
            name: name,
            slug: util.slugify(name),
            desc: v('desc'),
            picture: normalizePicture(v('picture'), v('type')),
            commander: !!v('commander'),
            is_combo: !!parseFloat(v("attack_multiplier")),
            is_defense: !!v('defense_card_id'),
            rarity: rarity,
            trait: v('trait'),
            set: parseInt(v('set')),
            type: parseInt(v('type')),
            hidden: !!v('hidden'),
            combo_card_id: parseInt(v("combo_card_id")) || null,
            health: parseInt(v('health')) || 0,
            attack: parseInt(v('attack')) || 0,
            health_multiplier: parseFloat(v('health_multiplier')) || 0,
            attack_multiplier: parseFloat(v('attack_multiplier')) || 0
        }, [].slice.apply(unit.querySelectorAll('unit > skill'))), [].slice.apply(unit.querySelectorAll('upgrade')));
    }

    function CardCollection(listResponseXML) {
        this.defaultInclude = ['deck'];

        listResponseXML = listResponseXML.map(function (responseXML) {
            return (new DOMParser).parseFromString(responseXML, 'application/xml');
        });

        this.items = listResponseXML.reduce(function (collection, xml) {
            return collection.concat([].slice.apply(xml.querySelectorAll('unit')).map(parseUnit));
        }, []);

        this.combos = listResponseXML.reduce(function (collection, xml) {
            return collection.concat(
                [].slice.apply(xml.querySelectorAll('combo'))
                    .filter(releaseDate)
                    .filter(validate_combo)
                    .map(parseCombo)
            );
        }, []);

        this.farmable = listResponseXML.reduce(function (farmable, xml) {
            return [].slice.apply(xml.querySelectorAll('rewards card')).reduce(function(farmable, card) {
                if (parseInt(card.parentNode.parentNode.querySelector('id').textContent) > 1000) {
                    return farmable;
                }

                farmable[card.getAttribute('id')] = true;

                return farmable;
            }, farmable);
        }, {});

        this.types = {
            "characters": this.combos.map(function (combo) { return combo.character; }),
            "items": this.combos.map(function (combo) { return combo.item; })
        }
    }

    CardCollection.prototype.COMBO_ROLE_CHARACTER = 'character';
    CardCollection.prototype.COMBO_ROLE_ITEM = 'item';
    CardCollection.prototype.COMBO_ROLE_PRECOMBO = 'precombo';

    CardCollection.prototype.getCards = function cardcollection__getCards(include) {
        include = include || this.defaultInclude;
        return this.items.map(categorize_card.bind(null, this))
            .filter(function (item) {
                return include.reduce(function (result, key) {
                    var exclude = "-" === key[0];
                    key = key.replace(/^[+-]/, '');

                    return exclude ? (result && ! item[key]) : (result || item[key]);
                }, false);
            }).map(flatten_card_category);
    };

    CardCollection.prototype.getComboRole = function cardcollection__getComboRole(card) {
        return -1 !== this.types.characters.indexOf(card.id) ? this.COMBO_ROLE_CHARACTER
            : -1 !== this.types.items.indexOf(card.id) ? this.COMBO_ROLE_ITEM
            : this.COMBO_ROLE_PRECOMBO;
    };

    CardCollection.prototype.isPrecombo = function cardcollection__isPrecombo(card) {
        return this.COMBO_ROLE_PRECOMBO === this.getComboRole(card);
    };

    CardCollection.prototype.isItem = function cardcollection__isItem(card) {
        return this.COMBO_ROLE_ITEM === this.getComboRole(card);
    };

    CardCollection.prototype.find = function cardcollection__find(options) {
        if ("string" === typeof options) {
            options = { "name": options }
        }

        var name = util.slugify(options.name);
        var include = options.include || this.defaultInclude;

        return this.items.filter(function (card) {
            return name === card.slug;
        }).map(categorize_card.bind(null, this)).sort(function (alpha, bravo) {
            return include.reduce(function (result, key) {
                var dir = "-" === key[0] ? -1 : 1;
                key = key.replace(/^[+-]/, '');

                return result || (bravo[key] - alpha[key]) * dir;
            }, 0);
        }).map(flatten_card_category)[0];
    };

    CardCollection.prototype.get = function cardcollection_(id, optional) {
        for (var i = 0, card; card = this.items[i]; i++) {
            if (id === card.id) {
                return card;
            }
        }

        if (optional) {
            return null;
        }

        throw new CardNotFound;
    };

    CardCollection.forLevel = CardCollection.prototype.forLevel = function cardcollection__forLevel(card, level) {
        card = upgrade_card(card, level);

        return new Card({
            id: card.id,
            name: card.name,
            image: card.picture,
            rarity: card.rarity,
            attack: card.attack,
            health: card.health,
            level: card.level,
            trait: card.trait,
            fuse: card.fuse,
            is_combo: card.is_combo,
            skills: Object.keys(card.skills).map(function (skill) {
                return {
                    type: skill,
                    value: Math.abs(card.skills[skill].x),
                    target: card.skills[skill].y ? (/\d/.test(card.skills[skill].y) ? "show" : "trait") : null
                };
            })
        });
    };

    CardCollection.prototype.getHydratedCombos = function cardcollection__getHydratedCombos(characterLevel, itemLevel) {
        return this.combos.map(hydrate_combo.bind(this, characterLevel, itemLevel)).filter(identity);
    };

    CardCollection.prototype.getCombo = function cardcollection__getCombo(alpha, bravo) {
        for (var i = 0, combo; combo = this.combos[i]; i++) {
            if (combo.character === alpha.id && combo.item === bravo.id) {
                return hydrate_combo.call(this, alpha.getLevelString(), bravo.getLevelString(), combo);
            } else if (combo.character === bravo.id && combo.item === alpha.id) {
                return hydrate_combo.call(this, bravo.getLevelString(), alpha.getLevelString(), combo);
            }
        }

        return null;
    };

    CardCollection.prototype.getRecipesIncluding = function cardcollection__getRecipesIncluding(card, level) {
        return this.combos.filter(function (combo) {
            return !!~[combo.card_id, combo.character, combo.item].indexOf(card.id);
        }).map(hydrate_combo.bind(this, level, level)).filter(identity);
    };

    return CardCollection;

});
<|endoftext|>