<commit_before>
    // 1 - Init and define default values [INIT]
    // 2 - Duplicates the dataset [INIT]
    // 3 - Mutate all_data with static metadata [INIT]
    // Filter by time values
    // Filter by attribute/ Selection
    // Find unique values from dataset
    // Remove missing data
    // Aggregates the data [REFRESH]
    // Sorts the data

    // 1 - Init and define default parameters
    vars.items_data = [];

    // In case we use functions for X/Y variables
    if(typeof vars.var_x !== "string" && typeof vars.var_x === "function") {
      vars.data.forEach(function(d, i) {
        d.__var_x = vars.var_x(d, i, vars);
      });
      vars.var_x = "__var_x";
    }

    if(typeof vars.var_y !== "string" && typeof vars.var_y === "function") {
      vars.data.forEach(function(d, i) {
        d.__var_y = vars.var_y(d, i, vars);
      });
      vars.var_y = "__var_y";
    }

    if(typeof vars.type === 'undefined') {
      vars.type = 'none';
    };

    // In case the current_time is set dynamically
    if(typeof vars.time.current_time === "function") {
      vars.time.current_time = vars.time.current_time(vars.data)
    }

    // Duplicate the dataset to prevent mutation
    if(vars.init) {

      // Get a copy of the whole dataset
      vars.all_data = JSON.parse(JSON.stringify(vars.data));

    }

    // Calculate vars.new_data which should contain two things
    // 1/ The list of all items (e.g. countries, products)
    // 2/ The metadata for each items
    if(vars.init || vars.refresh) {

      // Creates default ids `__id` and `__value` for dataset without any id
      if(typeof vars.var_id === 'undefined') {

        if(vars.new_data === null) {
          vars.new_data = vars.all_data;
        }

        vars.new_data = vars.new_data.map(function(d, i) {

          if(typeof d !== 'object') {
            var e = {}
            e.__id = i;
            e.__value = d;
            d = e;
          }

          d.__id = i;
          return d;

        })

        vars.var_id = '__id';

        if(typeof vars.var_text === 'undefined') {
          vars.var_text = '__id';
        }

      } else {

        vars.new_data = JSON.parse(JSON.stringify(vars.all_data));

      }

      // If time filter parameter is set, then keep values for this time
      if(typeof vars.time.filter != "undefined" && vars.time.filter.length > 0) {

        if(vars.dev) {
          console.log("[vars.time.filter]", vars.time.filter);
        }

        vars.new_data = vars.new_data.filter(function(d, i) {
          return vars.time.filter.indexOf(d[vars.time.var_time]) > -1;
        });

      }

      // If time filter interval is set, then keep values from this interval
      if(typeof vars.time.filter_interval != "undefined" && vars.time.filter_interval.length == 2) {

        if(vars.dev) {
          console.log("[vars.time.interval]", vars.time.filter_interval);
        }

        vars.new_data = vars.new_data.filter(function(d, i) {
          return (d[vars.time.var_time] >= vars.time.filter_interval[0]) && (d[vars.time.var_time] <= vars.time.filter_interval[1]);
        });

      }

      // Find unique values for various parameters
      vars.time.interval = d3.extent(vars.new_data, function(d) { return d[vars.time.var_time]; });
      vars.time.points = vistk.utils.find_unique_values(vars.new_data, vars.time.var_time);

      // Filter data by attribute
      // TODO: not sure we should remove data, but add an attribute instead would better
      if(vars.filter.length > 0) {

        if(vars.dev) {
          console.log("[vars.filter]", vars.filter);
        }

        vars.new_data = vars.new_data.filter(function(d) {
          // We don't keep values that are not in the vars.filter array
          return vars.filter.indexOf(d[vars.var_group]+"") > -1;
        });

      }

      var unique_data = [];

      var lookup_index = [];
      var lookup_size = 0;

      vars.new_data.forEach(function(d, i) {

        var index = -1;

        if(typeof lookup_index[d[vars.var_id]] === 'undefined') {

          index = lookup_size;
          lookup_size++;

          lookup_index[d[vars.var_id]] = index;

          utils.init_item(d);

          if(vars.filter.indexOf(d[vars.var_group]) > -1) {
            d.__filtered = true;
          }
          if(vars.highlight.indexOf(vars.var_id) > -1) {
            d.__highlighted = true;
          }
          if(vars.selection.indexOf(vars.var_id) > -1) {
            d.__selected = true;
          }

          d.__redraw = true;

          // Dup for metadata
          var dup = JSON.parse(JSON.stringify(d));
          dup.values = [];

          unique_data.push(dup);

        } else {

          index = lookup_index[d[vars.var_id]];

        }

        var v = {};
        v[vars.var_id] = d[vars.var_id];
        v[vars.time.var_time] = d[vars.time.var_time];
        v[vars.var_y] = d[vars.var_y];
        v[vars.var_x] = d[vars.var_x];
        v[vars.var_color] = d[vars.var_color];
        v[vars.var_size] = d[vars.var_size];

        unique_data[index].values.push(v);

      });

      vars.new_data = unique_data;

    }

    // Aggregate data
    if(typeof vars.set['__aggregated'] !== 'undefined' && vars.refresh) {

      if(vars.dev) {
        console.log("[vars.aggregate]", vars.aggregate);
      }

      // Do the nesting
      // Should make sure it works for a generc dataset
      // Also for time or none-time attributes
      nested_data = d3.nest()
        .key(function(d) {
          return d[vars.var_group];
        })
        .rollup(function(leaves) {

          // Generates a new dataset with aggregated data
          var aggregation = {};

          aggregation[vars.var_id] = leaves[0][vars.var_group];

          aggregation[vars.var_text] = leaves[0][vars.var_group];

          aggregation[vars.var_group] = leaves[0][vars.var_group];

          // Quick fix in case var_x is an ordinal scale
          if(vars.var_x !== vars.var_id && vars.var_x !== vars.time.var_time) {
            aggregation[vars.var_x] = d3.mean(leaves, function(d) {
              return d[vars.var_x];
            });
          } else {
            aggregation[vars.var_x] = leaves[0][vars.var_x];
          }

          if(vars.var_y !== vars.var_id && vars.var_y !== vars.time.var_time) {
            aggregation[vars.var_y] = d3.mean(leaves, function(d) {
              return d[vars.var_y];
            });
          } else {
            aggregation[vars.var_y] = leaves[0][vars.var_y];
          }

          aggregation[vars.var_r] = d3.sum(leaves, function(d) {
            return d[vars.var_r];
          });

          aggregation.piescatter = [];
          aggregation.piescatter[0] = {};
          aggregation.piescatter[1] = {};

          // Assuming all the time values are present in all items
          aggregation.values = d3.range(leaves[0].values.length).map(function(d, i) {
            var d = {};

            if(vars.var_x === vars.time.var_time) {
              d[vars.var_x] = leaves[0].values[i][vars.var_x];
            } else {
              d[vars.var_x] = 0;
            }

            // Init values
            d[vars.var_y] = 0;
            d[vars.var_r] = 0;

            // TODO: this is metadata, should not be duplicated every year
            d[vars.var_id] = leaves[0].values[i][vars.var_id];

            // Time var
            d[vars.time.var_time] = leaves[0].values[i][vars.time.var_time];
            return d;
          });

          // Assuming we only aggregate var_x, var_y, var_r
          leaves.forEach(function(d, i) {
            d.values.forEach(function(e, j) {
              if(vars.var_x !== vars.time.var_time) {
                aggregation.values[j][vars.var_x] += e[vars.var_x];
              }

              aggregation.values[j][vars.var_y] += e[vars.var_y];
              aggregation.values[j][vars.var_r] += e[vars.var_r];
            });
          });

          utils.init_item(aggregation);
          aggregation.__aggregated = true;
          aggregation.__redraw = true;

          if(typeof vars.share_cutoff != "undefined") {

            aggregation.piescatter[0][vars.var_share] = d3.sum(leaves, function(d) {

              if(vars.share_cutoff(d)) {
                return 1;
              } else {
                return 0;
              }
            });

            aggregation.piescatter[1][vars.var_share] = d3.sum(leaves, function(d) {

              if(!vars.share_cutoff(d)) {
                return 1;
              } else {
                return 0;
              }
            });

          }

          vars.columns.forEach(function(c) {

            if(c === vars.var_text || c === vars.var_group) {
              return;
            }

            aggregation[c] = d3.mean(leaves, function(d) {
              return d[c];
            });
          });

          return aggregation;
        })
        .entries(vars.new_data);

      // Transform key/value into values tab only
      if(typeof vars.set['__aggregated'] !== 'undefined' && vars.set['__aggregated']) {
        vars.new_data = vars.new_data.concat(nested_data.map(function(d) { return d.values; }));
      } else {
        vars.new_data = nested_data.map(function(d) { return d.values; });
      }

    }

    if(vars.init || vars.refresh) {

      // Links between items
      // Used for product space
      if(vars.links !== null && vars.type === 'productspace') {

        vars.links.forEach(function(d, i) {

          if(typeof d.source === "string") {
            d.source = vistk.utils.find_node_by_id(vars.nodes, d.source);
          }

          if(typeof d.target === "string") {
            d.target = vistk.utils.find_node_by_id(vars.nodes, d.target);
          }

          d.__redraw = true;

        });

      }

      // Flagging missing nodes with __missing true attribute
      if(typeof vars.nodes !== "undefined" && vars.type === 'productspace') {

        vars.new_data = utils.join(vars.nodes, vars.new_data, vars.var_node_id, vars.var_id, function(new_data, node) {
            var r = new_data;
            if(typeof node === 'undefined') {
              return;
            }
            r.x = node.x;
            r.y = node.y;
            r.__redraw = true;
            return r;
        });

        // Remove missing nodes
        // vars.new_data = vars.new_data.filter(function(d) {
        //  return !d.__missing;
        // });

        // Go through again the list of nodes
        // to make sure we display all the nodes
        vars.nodes.forEach(function(d, i) {

          var node = vistk.utils.find_node_coordinates_by_id(vars.new_data, vars.var_id, d[vars.var_node_id]);

          if(typeof node === "undefined") {

            d.values = [];
            d[vars.var_r] = 0;
            d[vars.var_id] = d.id;

            utils.init_item(d);
            d.__redraw = true;

            vars.new_data.push(d);

          }

        })

      }

    }

    // Sorting the dataset
    if(typeof vars.var_sort !== "undefined" && vars.refresh) {

      if(vars.dev) {
         console.log("[updating sort]", vars.var_sort, vars.var_sort_asc, vars.user_vars)
      }

      if(typeof vars.var_sort_asc !== "undefined" && !vars.var_sort_asc) {
        vars.new_data = vars.new_data.sort(function(a, b) { return d3.ascending(a[vars.var_sort], b[vars.var_sort]);});
      } else {
        vars.new_data = vars.new_data.sort(function(a, b) { return d3.descending(a[vars.var_sort], b[vars.var_sort]);});
      }
    }
<commit_msg>Fix for aggregation<commit_after>
    // 1 - Init and define default values [INIT]
    // 2 - Duplicates the dataset [INIT]
    // 3 - Mutate all_data with static metadata [INIT]
    // Filter by time values
    // Filter by attribute/ Selection
    // Find unique values from dataset
    // Remove missing data
    // Aggregates the data [REFRESH]
    // Sorts the data

    // 1 - Init and define default parameters
    vars.items_data = [];

    // In case we use functions for X/Y variables
    if(typeof vars.var_x !== "string" && typeof vars.var_x === "function") {
      vars.data.forEach(function(d, i) {
        d.__var_x = vars.var_x(d, i, vars);
      });
      vars.var_x = "__var_x";
    }

    if(typeof vars.var_y !== "string" && typeof vars.var_y === "function") {
      vars.data.forEach(function(d, i) {
        d.__var_y = vars.var_y(d, i, vars);
      });
      vars.var_y = "__var_y";
    }

    if(typeof vars.type === 'undefined') {
      vars.type = 'none';
    };

    // In case the current_time is set dynamically
    if(typeof vars.time.current_time === "function") {
      vars.time.current_time = vars.time.current_time(vars.data)
    }

    // Duplicate the dataset to prevent mutation
    if(vars.init) {

      // Get a copy of the whole dataset
      vars.all_data = JSON.parse(JSON.stringify(vars.data));

    }

    // Calculate vars.new_data which should contain two things
    // 1/ The list of all items (e.g. countries, products)
    // 2/ The metadata for each items
    if(vars.init || vars.refresh) {

      // Creates default ids `__id` and `__value` for dataset without any id
      if(typeof vars.var_id === 'undefined') {

        if(vars.new_data === null) {
          vars.new_data = vars.all_data;
        }

        vars.new_data = vars.new_data.map(function(d, i) {

          if(typeof d !== 'object') {
            var e = {}
            e.__id = i;
            e.__value = d;
            d = e;
          }

          d.__id = i;
          return d;

        })

        vars.var_id = '__id';

        if(typeof vars.var_text === 'undefined') {
          vars.var_text = '__id';
        }

      } else {

        vars.new_data = JSON.parse(JSON.stringify(vars.all_data));

      }

      // If time filter parameter is set, then keep values for this time
      if(typeof vars.time.filter != "undefined" && vars.time.filter.length > 0) {

        if(vars.dev) {
          console.log("[vars.time.filter]", vars.time.filter);
        }

        vars.new_data = vars.new_data.filter(function(d, i) {
          return vars.time.filter.indexOf(d[vars.time.var_time]) > -1;
        });

      }

      // If time filter interval is set, then keep values from this interval
      if(typeof vars.time.filter_interval != "undefined" && vars.time.filter_interval.length == 2) {

        if(vars.dev) {
          console.log("[vars.time.interval]", vars.time.filter_interval);
        }

        vars.new_data = vars.new_data.filter(function(d, i) {
          return (d[vars.time.var_time] >= vars.time.filter_interval[0]) && (d[vars.time.var_time] <= vars.time.filter_interval[1]);
        });

      }

      // Find unique values for various parameters
      vars.time.interval = d3.extent(vars.new_data, function(d) { return d[vars.time.var_time]; });
      vars.time.points = vistk.utils.find_unique_values(vars.new_data, vars.time.var_time);

      // Filter data by attribute
      // TODO: not sure we should remove data, but add an attribute instead would better
      if(vars.filter.length > 0) {

        if(vars.dev) {
          console.log("[vars.filter]", vars.filter);
        }

        vars.new_data = vars.new_data.filter(function(d) {
          // We don't keep values that are not in the vars.filter array
          return vars.filter.indexOf(d[vars.var_group]+"") > -1;
        });

      }

      var unique_data = [];

      var lookup_index = [];
      var lookup_size = 0;

      vars.new_data.forEach(function(d, i) {

        var index = -1;

        if(typeof lookup_index[d[vars.var_id]] === 'undefined') {

          index = lookup_size;
          lookup_size++;

          lookup_index[d[vars.var_id]] = index;

          utils.init_item(d);

          if(vars.filter.indexOf(d[vars.var_group]) > -1) {
            d.__filtered = true;
          }
          if(vars.highlight.indexOf(vars.var_id) > -1) {
            d.__highlighted = true;
          }
          if(vars.selection.indexOf(vars.var_id) > -1) {
            d.__selected = true;
          }

          d.__redraw = true;

          // Dup for metadata
          var dup = JSON.parse(JSON.stringify(d));
          dup.values = [];

          unique_data.push(dup);

        } else {

          index = lookup_index[d[vars.var_id]];

        }

        var v = {};
        v[vars.var_id] = d[vars.var_id];
        v[vars.time.var_time] = d[vars.time.var_time];
        v[vars.var_y] = d[vars.var_y];
        v[vars.var_x] = d[vars.var_x];
        v[vars.var_color] = d[vars.var_color];
        v[vars.var_size] = d[vars.var_size];

        unique_data[index].values.push(v);

      });

      vars.new_data = unique_data;

    }

    // Aggregate data
    if(typeof vars.set['__aggregated'] !== 'undefined' && vars.refresh) {

      if(vars.dev) {
        console.log("[vars.aggregate]", vars.aggregate);
      }

      // Do the nesting
      // Should make sure it works for a generc dataset
      // Also for time or none-time attributes
      nested_data = d3.nest()
        .key(function(d) {
          return d[vars.var_group];
        })
        .rollup(function(leaves) {

          // Generates a new dataset with aggregated data
          var aggregation = {};

          aggregation[vars.var_id] = leaves[0][vars.var_group];

          aggregation[vars.var_text] = leaves[0][vars.var_group];

          aggregation[vars.var_group] = leaves[0][vars.var_group];

          // Quick fix in case var_x is an ordinal scale
          if(vars.var_x !== vars.var_id && vars.var_x !== vars.time.var_time && vars.var_x !== vars.var_group) {
            aggregation[vars.var_x] = d3.mean(leaves, function(d) {
              return d[vars.var_x];
            });
          } else {
            aggregation[vars.var_x] = leaves[0][vars.var_x];
          }

          if(vars.var_y !== vars.var_id && vars.var_y !== vars.time.var_time) {
            aggregation[vars.var_y] = d3.mean(leaves, function(d) {
              return d[vars.var_y];
            });
          } else {
            aggregation[vars.var_y] = leaves[0][vars.var_y];
          }

          aggregation[vars.var_r] = d3.sum(leaves, function(d) {
            return d[vars.var_r];
          });

          aggregation.piescatter = [];
          aggregation.piescatter[0] = {};
          aggregation.piescatter[1] = {};

          // Assuming all the time values are present in all items
          aggregation.values = d3.range(leaves[0].values.length).map(function(d, i) {
            var d = {};

            if(vars.var_x === vars.time.var_time) {
              d[vars.var_x] = leaves[0].values[i][vars.var_x];
            } else {
              d[vars.var_x] = 0;
            }

            // Init values
            d[vars.var_y] = 0;
            d[vars.var_r] = 0;

            // TODO: this is metadata, should not be duplicated every year
            d[vars.var_id] = leaves[0].values[i][vars.var_id];

            // Time var
            d[vars.time.var_time] = leaves[0].values[i][vars.time.var_time];
            return d;
          });

          // Assuming we only aggregate var_x, var_y, var_r
          leaves.forEach(function(d, i) {
            d.values.forEach(function(e, j) {
              if(vars.var_x !== vars.time.var_time) {
                aggregation.values[j][vars.var_x] += e[vars.var_x];
              }

              aggregation.values[j][vars.var_y] += e[vars.var_y];
              aggregation.values[j][vars.var_r] += e[vars.var_r];
            });
          });

          utils.init_item(aggregation);
          aggregation.__aggregated = true;
          aggregation.__redraw = true;

          if(typeof vars.share_cutoff != "undefined") {

            aggregation.piescatter[0][vars.var_share] = d3.sum(leaves, function(d) {

              if(vars.share_cutoff(d)) {
                return 1;
              } else {
                return 0;
              }
            });

            aggregation.piescatter[1][vars.var_share] = d3.sum(leaves, function(d) {

              if(!vars.share_cutoff(d)) {
                return 1;
              } else {
                return 0;
              }
            });

          }

          vars.columns.forEach(function(c) {

            if(c === vars.var_text || c === vars.var_group) {
              return;
            }

            aggregation[c] = d3.mean(leaves, function(d) {
              return d[c];
            });
          });

          return aggregation;
        })
        .entries(vars.new_data);

      // Transform key/value into values tab only
      if(typeof vars.set['__aggregated'] !== 'undefined' && vars.set['__aggregated']) {
        vars.new_data = vars.new_data.concat(nested_data.map(function(d) { return d.values; }));
      } else {
        vars.new_data = nested_data.map(function(d) { return d.values; });
      }

    }

    if(vars.init || vars.refresh) {

      // Links between items
      // Used for product space
      if(vars.links !== null && vars.type === 'productspace') {

        vars.links.forEach(function(d, i) {

          if(typeof d.source === "string") {
            d.source = vistk.utils.find_node_by_id(vars.nodes, d.source);
          }

          if(typeof d.target === "string") {
            d.target = vistk.utils.find_node_by_id(vars.nodes, d.target);
          }

          d.__redraw = true;

        });

      }

      // Flagging missing nodes with __missing true attribute
      if(typeof vars.nodes !== "undefined" && vars.type === 'productspace') {

        vars.new_data = utils.join(vars.nodes, vars.new_data, vars.var_node_id, vars.var_id, function(new_data, node) {
            var r = new_data;
            if(typeof node === 'undefined') {
              return;
            }
            r.x = node.x;
            r.y = node.y;
            r.__redraw = true;
            return r;
        });

        // Remove missing nodes
        // vars.new_data = vars.new_data.filter(function(d) {
        //  return !d.__missing;
        // });

        // Go through again the list of nodes
        // to make sure we display all the nodes
        vars.nodes.forEach(function(d, i) {

          var node = vistk.utils.find_node_coordinates_by_id(vars.new_data, vars.var_id, d[vars.var_node_id]);

          if(typeof node === "undefined") {

            d.values = [];
            d[vars.var_r] = 0;
            d[vars.var_id] = d.id;

            utils.init_item(d);
            d.__redraw = true;

            vars.new_data.push(d);

          }

        })

      }

    }

    // Sorting the dataset
    if(typeof vars.var_sort !== "undefined" && vars.refresh) {

      if(vars.dev) {
         console.log("[updating sort]", vars.var_sort, vars.var_sort_asc, vars.user_vars)
      }

      if(typeof vars.var_sort_asc !== "undefined" && !vars.var_sort_asc) {
        vars.new_data = vars.new_data.sort(function(a, b) { return d3.ascending(a[vars.var_sort], b[vars.var_sort]);});
      } else {
        vars.new_data = vars.new_data.sort(function(a, b) { return d3.descending(a[vars.var_sort], b[vars.var_sort]);});
      }
    }
<|endoftext|>


<commit_before>/**
 * @overview A module that initializes the Gallery with Flickity
 * @module Gallery.js
*/

import Flickity from 'flickity';
import { ImgixSettings } from '../media/ImgixSettings';

export const Gallery = {

  /**
   * Sets up any galleries on the page
   * @returns {void}
  */
  init() {
    const galleryEls = document.querySelectorAll(`.js-gallery`);
    this.setupGalleries(galleryEls);
    this.setupImageGalleries();
  },

  /**
   * Instantiates Flickity on each gallery, with their respective options
   * @param {object} Gallery DOM elements to setup
   * @returns {void}
  */
  setupGalleries(galleryEls) {
    [...galleryEls].forEach((el) => {
      const options = JSON.parse(el.getAttribute(`data-options`));
      new Flickity(el, options);
    });
  },

  /**
   * Sets custom imgix settings for gallery images, instantiating Flickity and
   * fading in the gallery once the first image has loaded
   * @returns {void}
  */
  setupImageGalleries() {
    ImgixSettings.init({
      fluidClass: `imgix-fluid--gallery`,
      onLoad: (el) => {
        const currentGallery = el.closest(`.js-gallery--images`);

        if (el === currentGallery.firstElementChild) {
          this.setupGalleries([currentGallery]);
          currentGallery.classList.add(`is-loaded`);
        }
      },
    });
  },
};
<commit_msg>Add js extension required for proper jspm importing<commit_after>/**
 * @overview A module that initializes the Gallery with Flickity
 * @module Gallery.js
*/

import Flickity from 'flickity';
import { ImgixSettings } from '../media/ImgixSettings.js';

export const Gallery = {

  /**
   * Sets up any galleries on the page
   * @returns {void}
  */
  init() {
    const galleryEls = document.querySelectorAll(`.js-gallery`);
    this.setupGalleries(galleryEls);
    this.setupImageGalleries();
  },

  /**
   * Instantiates Flickity on each gallery, with their respective options
   * @param {object} Gallery DOM elements to setup
   * @returns {void}
  */
  setupGalleries(galleryEls) {
    [...galleryEls].forEach((el) => {
      const options = JSON.parse(el.getAttribute(`data-options`));
      new Flickity(el, options);
    });
  },

  /**
   * Sets custom imgix settings for gallery images, instantiating Flickity and
   * fading in the gallery once the first image has loaded
   * @returns {void}
  */
  setupImageGalleries() {
    ImgixSettings.init({
      fluidClass: `imgix-fluid--gallery`,
      onLoad: (el) => {
        const currentGallery = el.closest(`.js-gallery--images`);

        if (el === currentGallery.firstElementChild) {
          this.setupGalleries([currentGallery]);
          currentGallery.classList.add(`is-loaded`);
        }
      },
    });
  },
};
<|endoftext|>


<commit_before>'use strict';

var game = require('../game'),
    Phaser = require('phaser').Phaser;

var sprite;
var controls = {};
var testMap;
var puker = 1;
var jumper = 0;
var layer;
var grassyLayer;
var ability = 0;//0 = vomit, 1 = hover. THis is checked in puke() which is general perpose
var aCounter = 0;//this keeps track of how close we are to triggering an ability.
var emitter;
var emitting = false;
var emitterXvelocity;
var emitterXvelecoityMoving;
var baddies = [];

function createGameState() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.stage.backgroundColor = '#999999';

    testMap = game.add.tilemap('testMap');
    testMap.addTilesetImage('all_small', 'all_small');
    layer = testMap.createLayer('Tile Layer 1');
    grassyLayer = testMap.createLayer('Grass On Top');

    emitter = game.add.emitter(0, 0, 1);
    sprite = game.add.sprite(200, 200, 'player');
    sprite.anchor.setTo(0.65, 0.5);
    sprite.facing = 1;

    sprite.animations.add('walk', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]);
    sprite.animations.add('stand', [6]);

    sprite.animations.play('walk', 60, true);

    game.physics.arcade.enable(sprite);
    sprite.body.setSize(40, 144, 6, 14);
    game.physics.arcade.gravity.y = 300;

    game.physics.arcade.collide(sprite, layer);
    testMap.setCollisionBetween(8, 11, true, layer);
    testMap.setCollisionBetween(13, 17, true, layer);
    testMap.setCollisionBetween(19, 23, true, layer);
    testMap.setCollisionBetween(26, 29, true, layer);

    sprite.body.maxVelocity.x = 400;
    sprite.body.drag.x = 370;
    sprite.body.drag.y = 370;
    sprite.running = false;
    game.physics.enable(sprite, Phaser.Physics.ARCADE);
    sprite.body.gravity.y = 1000;

    game.camera.follow(sprite);
    layer.resizeWorld();

    emitter.makeParticles('vomit', [0,1,2,3], 200, true, true);

    // Attach the emitter to the sprite
    //sprite.addChild(emitter);

    //position the emitter relative to the sprite's anchor location
    emitter.y = 100;
    emitter.x = -250;

    emitterXvelocity = 700;
    emitter.minParticleSpeed.setTo(emitterXvelocity, 100);
    emitter.maxParticleSpeed.setTo(emitterXvelocity / 2, 600);

    emitter.gravity = 1;
    emitter.bounce.setTo(0.5, 0.5);
    emitter.angularDrag = 0;

    controls.left = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
    controls.right = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
    controls.run = game.input.keyboard.addKey(Phaser.Keyboard.X);
    controls.jump = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
    populateBaddies();
}

function updateGameState() {
    game.physics.arcade.collide(sprite, layer);
    game.physics.arcade.collide(emitter, layer);

    if (!sprite.running && controls.run.isDown) {
        sprite.running = true;
        sprite.body.maxVelocity.x = 700;
        sprite.body.drag.x = 470;
    }
    if (!controls.run.isDown && sprite.running) {
        sprite.running = false;
        sprite.body.maxVelocity.x = 400;
        sprite.body.drag.x = 370;
        emitterXvelecoityMoving = emitterXvelocity;
        emitter.minParticleSpeed.setTo(emitterXvelocity, 0);
    }

    var moving = false;
    if (controls.left.isDown) {
        moving = true;
        sprite.body.velocity.x -= 50;
        if (sprite.facing === 1) {
            sprite.scale.x = -1;
            sprite.facing = -1;
        }
        if (emitting) {
            emitter.maxParticleSpeed.x = (emitterXvelocity * sprite.facing) + sprite.body.velocity.x;
            emitter.minParticleSpeed.x = ((emitterXvelocity * sprite.facing)/2) + sprite.body.velocity.x;
        }
    }
    if (controls.right.isDown) {
        moving = true;
        sprite.body.velocity.x += 50;
        if (sprite.facing === -1) {
            sprite.scale.x = 1;
            sprite.facing = 1;
        }
        if (emitting) {
            emitter.maxParticleSpeed.x = (emitterXvelocity * sprite.facing) + sprite.body.velocity.x;
            emitter.minParticleSpeed.x = ((emitterXvelocity * sprite.facing)/2) + sprite.body.velocity.x;
        }
    }
    if (!moving) {
        if (sprite.animations.currentAnim.name !== 'stand') {
            sprite.animations.play('stand');
        }
    } else {
        if (sprite.animations.currentAnim.name !== 'walk') {
            sprite.animations.play('walk', 60, true);
        }
    }
    if(jumper > 0) {jumper--;}
    if(sprite.body.onFloor() && controls.jump.isDown && jumper == 0){
       jumper = 20;
       sprite.body.velocity.y = -500;
       if(sprite.running){
           sprite.body.velocity.y -= 100;
       }
       puker++;
    }
    else if (controls.jump.isDown && sprite.body.velocity.y < -300){
        sprite.body.velocity.y -= 20;
    }
    if(puker % 4 == 0){
       puke();
    }

    if (emitting) {
        emitter.emitParticle();
        //emitter.x += 10;
        //emitter.position = sprite.position;
        emitter.x = sprite.x+10;
        emitter.y = sprite.y;
    }
 if(sprite.body.y > 700){gameOver();}
}

function gameOver(){
    game.state.start("gameState");
}

function puke(){
    puker = 1;
    if(ability == 0){
        var bullet = game.add.sprite(sprite.x, sprite.y + 30, 'test2');
        game.physics.arcade.enable(bullet);
        bullet.update = bulletColide;
        bullet.facing = sprite.facing;
        bullet.body.allowGravity = false;
        game.time.events.add(5000, bulletDeath, bullet);
    }else if (ability == 1){
        sprite.body.gravity.y = 0;
        sprite.body.velocity.y = 0;
        sprite.body.y = sprite.body.y - 10;
        game.time.events.add(1500, endHover, sprite);
    }
    emitting = true;
    game.time.events.add(1000, function() {emitting = false;});
}
function endHover(){
    this.body.gravity.y = 1000;
}

function bulletDeath(){
    this.kill();
}
function populateBaddies(){

    var baddy = game.add.sprite(500, 345, 'test2');
        game.physics.arcade.enable(baddy);
        baddy.update = baddyColide;
        baddy.body.allowGravity = false;
baddies.push(baddy);
}
function baddyColide(){

    if(game.physics.arcade.collide(this, sprite)){gameOver();}
    game.physics.arcade.collide(this, layer);
}

function killBaddy(a){
baddies[a].kill();
}

function bulletColide(){
    this.body.velocity.x = 600 * this.facing;
    game.physics.arcade.collide(this, layer);
    if(game.physics.arcade.collide(this, baddies[0])){ killBaddy(0);}

    if (!this.body.touching.none) {
        this.facing = this.facing * -1;
    }
}

var gameState = {
    create: createGameState,
    update: updateGameState
};

module.exports = gameState;
<commit_msg>death pause<commit_after>'use strict';

var game = require('../game'),
    Phaser = require('phaser').Phaser;

var sprite;
var controls = {};
var testMap;
var puker = 1;
var jumper = 0;
var layer;
var grassyLayer;
var ability = 0;//0 = vomit, 1 = hover. THis is checked in puke() which is general perpose
var aCounter = 0;//this keeps track of how close we are to triggering an ability.
var emitter;
var emitting = false;
var emitterXvelocity;
var emitterXvelecoityMoving;
var baddies = [];

function createGameState() {
    game.physics.startSystem(Phaser.Physics.ARCADE);
    game.stage.backgroundColor = '#999999';

    testMap = game.add.tilemap('testMap');
    testMap.addTilesetImage('all_small', 'all_small');
    layer = testMap.createLayer('Tile Layer 1');
    grassyLayer = testMap.createLayer('Grass On Top');

    emitter = game.add.emitter(0, 0, 1);
    sprite = game.add.sprite(200, 200, 'player');
    sprite.anchor.setTo(0.65, 0.5);
    sprite.facing = 1;

    sprite.animations.add('walk', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]);
    sprite.animations.add('stand', [6]);

    sprite.animations.play('walk', 60, true);

    game.physics.arcade.enable(sprite);
    sprite.body.setSize(40, 144, 6, 14);
    game.physics.arcade.gravity.y = 300;

    game.physics.arcade.collide(sprite, layer);
    testMap.setCollisionBetween(8, 11, true, layer);
    testMap.setCollisionBetween(13, 17, true, layer);
    testMap.setCollisionBetween(19, 23, true, layer);
    testMap.setCollisionBetween(26, 29, true, layer);

    sprite.body.maxVelocity.x = 400;
    sprite.body.drag.x = 370;
    sprite.body.drag.y = 370;
    sprite.running = false;
    game.physics.enable(sprite, Phaser.Physics.ARCADE);
    sprite.body.gravity.y = 1000;

    game.camera.follow(sprite);
    layer.resizeWorld();

    emitter.makeParticles('vomit', [0,1,2,3], 200, true, true);

    // Attach the emitter to the sprite
    //sprite.addChild(emitter);

    //position the emitter relative to the sprite's anchor location
    emitter.y = 100;
    emitter.x = -250;

    emitterXvelocity = 700;
    emitter.minParticleSpeed.setTo(emitterXvelocity, 100);
    emitter.maxParticleSpeed.setTo(emitterXvelocity / 2, 600);

    emitter.gravity = 1;
    emitter.bounce.setTo(0.5, 0.5);
    emitter.angularDrag = 0;

    controls.left = game.input.keyboard.addKey(Phaser.Keyboard.LEFT);
    controls.right = game.input.keyboard.addKey(Phaser.Keyboard.RIGHT);
    controls.run = game.input.keyboard.addKey(Phaser.Keyboard.X);
    controls.jump = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
    populateBaddies();
}

function updateGameState() {
    game.physics.arcade.collide(sprite, layer);
    game.physics.arcade.collide(emitter, layer);

    if (!sprite.running && controls.run.isDown) {
        sprite.running = true;
        sprite.body.maxVelocity.x = 700;
        sprite.body.drag.x = 470;
    }
    if (!controls.run.isDown && sprite.running) {
        sprite.running = false;
        sprite.body.maxVelocity.x = 400;
        sprite.body.drag.x = 370;
        emitterXvelecoityMoving = emitterXvelocity;
        emitter.minParticleSpeed.setTo(emitterXvelocity, 0);
    }

    var moving = false;
    if (controls.left.isDown) {
        moving = true;
        sprite.body.velocity.x -= 50;
        if (sprite.facing === 1) {
            sprite.scale.x = -1;
            sprite.facing = -1;
        }
        if (emitting) {
            emitter.maxParticleSpeed.x = (emitterXvelocity * sprite.facing) + sprite.body.velocity.x;
            emitter.minParticleSpeed.x = ((emitterXvelocity * sprite.facing)/2) + sprite.body.velocity.x;
        }
    }
    if (controls.right.isDown) {
        moving = true;
        sprite.body.velocity.x += 50;
        if (sprite.facing === -1) {
            sprite.scale.x = 1;
            sprite.facing = 1;
        }
        if (emitting) {
            emitter.maxParticleSpeed.x = (emitterXvelocity * sprite.facing) + sprite.body.velocity.x;
            emitter.minParticleSpeed.x = ((emitterXvelocity * sprite.facing)/2) + sprite.body.velocity.x;
        }
    }
    if (!moving) {
        if (sprite.animations.currentAnim.name !== 'stand') {
            sprite.animations.play('stand');
        }
    } else {
        if (sprite.animations.currentAnim.name !== 'walk') {
            sprite.animations.play('walk', 60, true);
        }
    }
    if(jumper > 0) {jumper--;}
    if(sprite.body.onFloor() && controls.jump.isDown && jumper == 0){
       jumper = 20;
       sprite.body.velocity.y = -500;
       if(sprite.running){
           sprite.body.velocity.y -= 100;
       }
       puker++;
    }
    else if (controls.jump.isDown && sprite.body.velocity.y < -300){
        sprite.body.velocity.y -= 20;
    }
    if(puker % 4 == 0){
       puke();
    }

    if (emitting) {
        emitter.emitParticle();
        //emitter.x += 10;
        //emitter.position = sprite.position;
        emitter.x = sprite.x+10;
        emitter.y = sprite.y;
    }
 if(sprite.body.y > 700){gameOver();}
}

function gameOver(){
//TODO you fail
    game.time.events.add(1000, reset);
}
function reset(){
    game.state.start("gameState");
}

function puke(){
    puker = 1;
    if(ability == 0){
        var bullet = game.add.sprite(sprite.x, sprite.y + 30, 'test2');
        game.physics.arcade.enable(bullet);
        bullet.update = bulletColide;
        bullet.facing = sprite.facing;
        bullet.body.allowGravity = false;
        game.time.events.add(5000, bulletDeath, bullet);
    }else if (ability == 1){
        sprite.body.gravity.y = 0;
        sprite.body.velocity.y = 0;
        sprite.body.y = sprite.body.y - 10;
        game.time.events.add(1500, endHover, sprite);
    }
    emitting = true;
    game.time.events.add(1000, function() {emitting = false;});
}
function endHover(){
    this.body.gravity.y = 1000;
}

function bulletDeath(){
    this.kill();
}
function populateBaddies(){

    var baddy = game.add.sprite(500, 345, 'test2');
        game.physics.arcade.enable(baddy);
        baddy.update = baddyColide;
        baddy.body.allowGravity = false;
baddies.push(baddy);
}
function baddyColide(){

    if(game.physics.arcade.collide(this, sprite)){gameOver();}
    game.physics.arcade.collide(this, layer);
}

function killBaddy(a){
baddies[a].kill();
}

function bulletColide(){
    this.body.velocity.x = 600 * this.facing;
    game.physics.arcade.collide(this, layer);
    if(game.physics.arcade.collide(this, baddies[0])){ killBaddy(0);}

    if (!this.body.touching.none) {
        this.facing = this.facing * -1;
    }
}

var gameState = {
    create: createGameState,
    update: updateGameState
};

module.exports = gameState;
<|endoftext|>


<commit_before>describe("About Expects", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(false).toBeTruthy(); //This should be true
  });

  //To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = 1 + 1;

	  expect(actualValue === expectedValue).toBeTruthy();
  });

  //Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
	  expect(actualValue).toEqual(expectedValue);
  });

  //Sometimes you need to be really exact about what you "type".
  it("should assert equality with ===", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
	  expect(actualValue).toBe(expectedValue);
  });

  //Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
	  expect(1 + 1).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Completed AboutExpects.js<commit_after>describe("About Expects", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(true).toBeTruthy(); //This should be true
  });

  //To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
	  var expectedValue = 2;
	  var actualValue = 1 + 1;

	  expect(actualValue === expectedValue).toBeTruthy();
  });

  //Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
	  var expectedValue = 2;
	  var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
	  expect(actualValue).toEqual(expectedValue);
  });

  //Sometimes you need to be really exact about what you "type".
  it("should assert equality with ===", function () {
	  var expectedValue = '2';
	  var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
	  expect(actualValue).toBe(expectedValue);
  });

  //Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
	  expect(1 + 1).toEqual(2);
  });
});
<|endoftext|>


<commit_before>var Mode = require('./Mode');

function Teams() {
    Mode.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 1;
    this.name = "Teams";
    this.decayMod = 1.5;
    this.packetLB = 50;
    this.haveTeams = true;
    this.colorFuzziness = 32;

    // Special
    this.teamAmount = 3; // Amount of teams. Having more than 3 teams will cause the leaderboard to work incorrectly (client issue).
    this.colors = [{
        'r': 223,
        'g': 0,
        'b': 0
    }, {
        'r': 0,
        'g': 223,
        'b': 0
    }, {
        'r': 0,
        'g': 0,
        'b': 223
    }, ]; // Make sure you add extra colors here if you wish to increase the team amount [Default colors are: Red, Green, Blue]
    this.nodes = []; // Teams
}

module.exports = Teams;
Teams.prototype = new Mode();

//Gamemode Specific Functions

Teams.prototype.fuzzColorComponent = function(component) {
    component += Math.random() * this.colorFuzziness >> 0;
    return component;
};

Teams.prototype.getTeamColor = function(team) {
    var color = this.colors[team];
    return {
        r: this.fuzzColorComponent(color.r),
        b: this.fuzzColorComponent(color.b),
        g: this.fuzzColorComponent(color.g)
    };
};

// Override

Teams.prototype.onPlayerSpawn = function(gameServer, player) {
    // Random color based on team
    player.color = this.getTeamColor(player.team);
    // Spawn player
    gameServer.spawnPlayer(player);
};

Teams.prototype.onServerInit = function(gameServer) {
    // Set up teams
    for (var i = 0; i < this.teamAmount; i++) {
        this.nodes[i] = [];
    }

    // migrate current players to team mode
    for (var i = 0; i < gameServer.clients.length; i++) {
        var client = gameServer.clients[i].playerTracker;
        this.onPlayerInit(client);
        client.color = this.getTeamColor(client.team);
        for (var j = 0; j < client.cells.length; j++) {
            var cell = client.cells[j];
            cell.setColor(client.color);
            this.nodes[client.team].push(cell);
        }
    }
};

Teams.prototype.onPlayerInit = function(player) {
    // Get random team
    player.team = Math.floor(Math.random() * this.teamAmount);
};

Teams.prototype.onCellAdd = function(cell) {
    // Add to team list
    this.nodes[cell.owner.getTeam()].push(cell);
};

Teams.prototype.onCellRemove = function(cell) {
    // Remove from team list
    var index = this.nodes[cell.owner.getTeam()].indexOf(cell);
    if (index != -1) {
        this.nodes[cell.owner.getTeam()].splice(index, 1);
    }
};

Teams.prototype.onCellMove = function(x1, y1, cell) {
    var team = cell.owner.getTeam();
    var r = cell.getSize();

    // Find team
    for (var i = 0; i < cell.owner.visibleNodes.length; i++) {
        // Only collide with player cells
        var check = cell.owner.visibleNodes[i];

        if ((check.getType() != 0) || (cell.owner == check.owner)) {
            continue;
        }

        // Collision with teammates
        if (check.owner.getTeam() == team) {
            // Check if in collision range
            var collisionDist = check.getSize() + r; // Minimum distance between the 2 cells
            if (!cell.simpleCollide(x1, y1, check, collisionDist)) {
                // Skip
                continue;
            }

            // First collision check passed... now more precise checking
            dist = cell.getDist(cell.position.x, cell.position.y, check.position.x, check.position.y);

            // Calculations
            if (dist < collisionDist) { // Collided
                // The moving cell pushes the colliding cell
                var newDeltaY = check.position.y - y1;
                var newDeltaX = check.position.x - x1;
                var newAngle = Math.atan2(newDeltaX, newDeltaY);

                var move = collisionDist - dist;

                check.position.x = check.position.x + (move * Math.sin(newAngle)) >> 0;
                check.position.y = check.position.y + (move * Math.cos(newAngle)) >> 0;
            }
        }
    }
};

Teams.prototype.updateLB = function(gameServer) {
    var total = 0;
    var teamMass = [];
    // Get mass
    for (var i = 0; i < this.teamAmount; i++) {
        // Set starting mass
        teamMass[i] = 0;

        // Loop through cells
        for (var j = 0; j < this.nodes[i].length; j++) {
            var cell = this.nodes[i][j];

            if (!cell) {
                continue;
            }

            teamMass[i] += cell.mass;
            total += cell.mass;
        }
    }
    // Calc percentage
    for (var i = 0; i < this.teamAmount; i++) {
        // No players
        if (total <= 0) {
            continue;
        }

        gameServer.leaderboard[i] = teamMass[i] / total;
    }
};
<commit_msg>Collision update for Team mode<commit_after>var Mode = require('./Mode');

function Teams() {
    Mode.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 1;
    this.name = "Teams";
    this.decayMod = 1.5;
    this.packetLB = 50;
    this.haveTeams = true;
    this.colorFuzziness = 32;

    // Special
    this.teamAmount = 3; // Amount of teams. Having more than 3 teams will cause the leaderboard to work incorrectly (client issue).
    this.colors = [{
        'r': 223,
        'g': 0,
        'b': 0
    }, {
        'r': 0,
        'g': 223,
        'b': 0
    }, {
        'r': 0,
        'g': 0,
        'b': 223
    }, ]; // Make sure you add extra colors here if you wish to increase the team amount [Default colors are: Red, Green, Blue]
    this.nodes = []; // Teams
}

module.exports = Teams;
Teams.prototype = new Mode();

//Gamemode Specific Functions

Teams.prototype.fuzzColorComponent = function(component) {
    component += Math.random() * this.colorFuzziness >> 0;
    return component;
};

Teams.prototype.getTeamColor = function(team) {
    var color = this.colors[team];
    return {
        r: this.fuzzColorComponent(color.r),
        b: this.fuzzColorComponent(color.b),
        g: this.fuzzColorComponent(color.g)
    };
};

// Override

Teams.prototype.onPlayerSpawn = function(gameServer, player) {
    // Random color based on team
    player.color = this.getTeamColor(player.team);
    // Spawn player
    gameServer.spawnPlayer(player);
};

Teams.prototype.onServerInit = function(gameServer) {
    // Set up teams
    for (var i = 0; i < this.teamAmount; i++) {
        this.nodes[i] = [];
    }

    // migrate current players to team mode
    for (var i = 0; i < gameServer.clients.length; i++) {
        var client = gameServer.clients[i].playerTracker;
        this.onPlayerInit(client);
        client.color = this.getTeamColor(client.team);
        for (var j = 0; j < client.cells.length; j++) {
            var cell = client.cells[j];
            cell.setColor(client.color);
            this.nodes[client.team].push(cell);
        }
    }
};

Teams.prototype.onPlayerInit = function(player) {
    // Get random team
    player.team = Math.floor(Math.random() * this.teamAmount);
};

Teams.prototype.onCellAdd = function(cell) {
    // Add to team list
    this.nodes[cell.owner.getTeam()].push(cell);
};

Teams.prototype.onCellRemove = function(cell) {
    // Remove from team list
    var index = this.nodes[cell.owner.getTeam()].indexOf(cell);
    if (index != -1) {
        this.nodes[cell.owner.getTeam()].splice(index, 1);
    }
};

Teams.prototype.onCellMove = function(x1, y1, cell) {
    var team = cell.owner.getTeam();
    var r = cell.getSize();

    // Find team
    for (var i = 0; i < cell.owner.visibleNodes.length; i++) {
        // Only collide with player cells
        var check = cell.owner.visibleNodes[i];

        if ((check.getType() != 0) || (cell.owner == check.owner)) {
            continue;
        }

        // Collision with teammates
        if (check.owner.getTeam() == team) {
            // Check if in collision range
            var collisionDist = check.getSize() + r; // Minimum distance between the 2 cells
            var dist = cell.getDist(cell.position.x, cell.position.y, check.position.x, check.position.y);

            // Calculations
            if (dist < collisionDist) { // Collided
                // The moving cell pushes the colliding cell
                // Strength however depends on cell1 speed divided by cell2 speed
                var speed1 = cell.getSpeed();
                var speed2 = check.getSpeed();
                var mult = Math.min(Math.max(speed1 / speed2, 2), 0.5); // Limit from 0.5 to 2 not to have bugs

                var newDeltaY = check.position.y - y1;
                var newDeltaX = check.position.x - x1;
                var newAngle = Math.atan2(newDeltaX, newDeltaY);

                var move = (collisionDist - dist) * mult;

                check.position.x = check.position.x + (move * Math.sin(newAngle)) >> 0;
                check.position.y = check.position.y + (move * Math.cos(newAngle)) >> 0;
            }
        }
    }
};

Teams.prototype.updateLB = function(gameServer) {
    var total = 0;
    var teamMass = [];
    // Get mass
    for (var i = 0; i < this.teamAmount; i++) {
        // Set starting mass
        teamMass[i] = 0;

        // Loop through cells
        for (var j = 0; j < this.nodes[i].length; j++) {
            var cell = this.nodes[i][j];

            if (!cell) {
                continue;
            }

            teamMass[i] += cell.mass;
            total += cell.mass;
        }
    }
    // Calc percentage
    for (var i = 0; i < this.teamAmount; i++) {
        // No players
        if (total <= 0) {
            continue;
        }

        gameServer.leaderboard[i] = teamMass[i] / total;
    }
};
<|endoftext|>


<commit_before>describe("About Expects", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(true).toBeTruthy(); //This should be true
  });

  //To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
	  var expectedValue = 2;
	  var actualValue = 1 + 1;

	  expect(actualValue === expectedValue).toBeTruthy();
  });

  //Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
	  expect(actualValue).toEqual(expectedValue);
  });

  //Sometimes you need to be really exact about what you "type".
  it("should assert equality with ===", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
	  expect(actualValue).toBe(expectedValue);
  });

  //Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
	  expect(1 + 1).toEqual(FILL_ME_IN);
  });
});
<commit_msg>Fix 'should assert equality a better way'<commit_after>describe("About Expects", function() {

  //We shall contemplate truth by testing reality, via spec expectations.
  it("should expect true", function() {
    expect(true).toBeTruthy(); //This should be true
  });

  //To understand reality, we must compare our expectations against reality.
  it("should expect equality", function () {
	  var expectedValue = 2;
	  var actualValue = 1 + 1;

	  expect(actualValue === expectedValue).toBeTruthy();
  });

  //Some ways of asserting equality are better than others.
  it("should assert equality a better way", function () {
	  var expectedValue = 2;
	  var actualValue = 1 + 1;

  // toEqual() compares using common sense equality.
	  expect(actualValue).toEqual(expectedValue);
  });

  //Sometimes you need to be really exact about what you "type".
  it("should assert equality with ===", function () {
	  var expectedValue = FILL_ME_IN;
	  var actualValue = (1 + 1).toString();

  // toBe() will always use === to compare.
	  expect(actualValue).toBe(expectedValue);
  });

  //Sometimes we will ask you to fill in the values.
  it("should have filled in values", function () {
	  expect(1 + 1).toEqual(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>import './game-display.scss'

import $ from 'jquery'

import PlayerDisplay from './player-display'
import formatTime from '../../utils/formatTime'
import { shouldDisableFullScreen } from 'bemuse/devtools/query-flags'
import screenfull from 'screenfull'

export class GameDisplay {
  constructor({ game, context, backgroundImagePromise, video }) {
    this._game = game
    this._context = context
    const skinData = context.skinData
    this._players = new Map(
      game.players.map(player => [player, new PlayerDisplay(player, skinData)])
    )
    this._stateful = {}
    this._wrapper = this._createWrapper({
      backgroundImagePromise,
      video,
      panelPlacement: game.players[0].options.placement,
      infoPanelPosition: skinData.infoPanelPosition,
    })
    this._createTouchEscapeButton()
    this._createFullScreenButton()
    this._escapeHintShown = false
  }
  setEscapeHandler(escapeHandler) {
    this._onEscape = escapeHandler
  }
  setReplayHandler(replayHandler) {
    this._onReplay = replayHandler
  }
  start() {
    this._started = new Date().getTime()
    let player = this._game.players[0]
    let songInfo = player.notechart.songInfo
    this._stateful['song_title'] = songInfo.title
    this._stateful['song_artist'] = songInfo.artist
    this._duration = player.notechart.duration
  }
  destroy() {
    this._context.destroy()
  }
  update(gameTime, gameState) {
    let time = (new Date().getTime() - this._started) / 1000
    let data = this._getData(time, gameTime, gameState)
    this._updateStatefulData(time, gameTime, gameState)
    this._context.render(Object.assign({}, this._stateful, data))
    if (this._video && !this._videoStarted && gameTime >= this._videoOffset) {
      this._video.volume = 0
      this._video.play()
      this._video.classList.add('is-playing')
      this._videoStarted = true
    }
    if (this._game.options.tutorial) {
      const TUTORIAL_ESCAPE_HINT_SHOW_TIME = 101.123595506
      if (
        gameTime >= TUTORIAL_ESCAPE_HINT_SHOW_TIME &&
        !this._escapeHintShown
      ) {
        this._escapeHintShown = true
        this._escapeHint.classList.add('is-shown')
      }
    }
  }
  _getData(time, gameTime, gameState) {
    let data = {}
    data['tutorial'] = this._game.options.tutorial ? 'yes' : 'no'
    data['t'] = time
    data['gameTime'] = gameTime
    data['ready'] = this._getReady(gameState)
    data['song_time'] = this._getSongTime(gameTime)
    for (let [player, playerDisplay] of this._players) {
      let playerState = gameState.player(player)
      let playerData = playerDisplay.update(time, gameTime, playerState)
      for (let key in playerData) {
        data[`p${player.number}_${key}`] = playerData[key]
      }
    }
    return data
  }
  _updateStatefulData(time, gameTime, gameState) {
    let data = this._stateful
    if (data['started'] === undefined && gameState.started) {
      data['started'] = time
    }
    if (data['gettingStarted'] === undefined && gameState.gettingStarted) {
      data['gettingStarted'] = time
    }
  }
  _getSongTime(gameTime) {
    return (
      formatTime(Math.min(this._duration, Math.max(0, gameTime))) +
      ' / ' +
      formatTime(this._duration)
    )
  }
  _getReady(gameState) {
    let f = gameState.readyFraction
    return f > 0.5 ? Math.pow(1 - (f - 0.5) / 0.5, 2) : 0
  }
  _createWrapper({
    backgroundImagePromise,
    video,
    panelPlacement,
    infoPanelPosition,
  }) {
    var $wrapper = $('

')
      .attr('data-panel-placement', panelPlacement)
      .attr('data-info-panel-position', infoPanelPosition)
      .append('

')
      .append(this.view)
    if (backgroundImagePromise) {
      Promise.resolve(backgroundImagePromise).then(image =>
        $wrapper.find('.js-back-image').append(image)
      )
    }
    if (video) {
      this._video = video.element
      this._videoOffset = video.offset
      $(video.element)
        .addClass('game-display--video-bg')
        .appendTo($wrapper)
    }
    return $wrapper[0]
  }
  _createTouchEscapeButton() {
    const touchButtons = document.createElement('div')
    touchButtons.className = 'game-display--touch-buttons is-left'
    this.wrapper.appendChild(touchButtons)
    touchButtons.classList.add('is-visible')
    const addTouchButton = (className, onClick) => {
      let button = createTouchButton(onClick, className)
      touchButtons.appendChild(button)
    }
    addTouchButton('game-display--touch-escape-button', () => this._onEscape())
    addTouchButton('game-display--touch-replay-button', () => this._onReplay())

    const escapeHint = document.createElement('div')
    escapeHint.textContent = 'Click or press Esc to exit the tutorial'
    escapeHint.className = 'game-display--escape-hint'
    this._escapeHint = escapeHint
    touchButtons.appendChild(escapeHint)
  }
  _createFullScreenButton() {
    if (shouldDisableFullScreen() || !screenfull.enabled) {
      return
    }
    const touchButtons = document.createElement('div')
    touchButtons.className = 'game-display--touch-buttons is-visible is-right'
    this.wrapper.appendChild(touchButtons)
    const onClick = () => {
      screenfull.request()
    }
    const button = createTouchButton(
      onClick,
      'game-display--touch-fullscreen-button'
    )
    touchButtons.appendChild(button)
  }
  get context() {
    return this._context
  }
  get view() {
    return this._context.view
  }
  get wrapper() {
    return this._wrapper
  }
}

function createTouchButton(onClick, className) {
  let button = document.createElement('button')
  button.addEventListener(
    'touchstart',
    e => {
      e.stopPropagation()
    },
    true
  )
  button.onclick = e => {
    e.preventDefault()
    onClick()
  }
  button.className = className
  return button
}

export default GameDisplay
<commit_msg>Fix CodeClimate warnings<commit_after>import './game-display.scss'

import $ from 'jquery'

import PlayerDisplay from './player-display'
import formatTime from '../../utils/formatTime'
import { shouldDisableFullScreen } from 'bemuse/devtools/query-flags'
import screenfull from 'screenfull'

export class GameDisplay {
  constructor({ game, context, backgroundImagePromise, video }) {
    this._game = game
    this._context = context
    const skinData = context.skinData
    this._players = new Map(
      game.players.map(player => [player, new PlayerDisplay(player, skinData)])
    )
    this._stateful = {}
    this._wrapper = this._createWrapper({
      backgroundImagePromise,
      video,
      panelPlacement: game.players[0].options.placement,
      infoPanelPosition: skinData.infoPanelPosition,
    })
    this._createTouchEscapeButton()
    this._createFullScreenButton()
    this._escapeHintShown = false
  }
  setEscapeHandler(escapeHandler) {
    this._onEscape = escapeHandler
  }
  setReplayHandler(replayHandler) {
    this._onReplay = replayHandler
  }
  start() {
    this._started = new Date().getTime()
    let player = this._game.players[0]
    let songInfo = player.notechart.songInfo
    this._stateful['song_title'] = songInfo.title
    this._stateful['song_artist'] = songInfo.artist
    this._duration = player.notechart.duration
  }
  destroy() {
    this._context.destroy()
  }
  update(gameTime, gameState) {
    let time = (new Date().getTime() - this._started) / 1000
    let data = this._getData(time, gameTime, gameState)
    this._updateStatefulData(time, gameTime, gameState)
    this._context.render(Object.assign({}, this._stateful, data))
    this._synchronizeVideo(gameTime)
    this._synchronizeTutorialEscapeHint(gameTime)
  }
  _synchronizeVideo(gameTime) {
    if (this._video && !this._videoStarted && gameTime >= this._videoOffset) {
      this._video.volume = 0
      this._video.play()
      this._video.classList.add('is-playing')
      this._videoStarted = true
    }
  }
  _synchronizeTutorialEscapeHint(gameTime) {
    if (this._game.options.tutorial) {
      const TUTORIAL_ESCAPE_HINT_SHOW_TIME = 101.123595506
      if (
        gameTime >= TUTORIAL_ESCAPE_HINT_SHOW_TIME &&
        !this._escapeHintShown
      ) {
        this._escapeHintShown = true
        this._escapeHint.classList.add('is-shown')
      }
    }
  }
  _getData(time, gameTime, gameState) {
    let data = {}
    data['tutorial'] = this._game.options.tutorial ? 'yes' : 'no'
    data['t'] = time
    data['gameTime'] = gameTime
    data['ready'] = this._getReady(gameState)
    data['song_time'] = this._getSongTime(gameTime)
    for (let [player, playerDisplay] of this._players) {
      let playerState = gameState.player(player)
      let playerData = playerDisplay.update(time, gameTime, playerState)
      for (let key in playerData) {
        data[`p${player.number}_${key}`] = playerData[key]
      }
    }
    return data
  }
  _updateStatefulData(time, gameTime, gameState) {
    let data = this._stateful
    if (data['started'] === undefined && gameState.started) {
      data['started'] = time
    }
    if (data['gettingStarted'] === undefined && gameState.gettingStarted) {
      data['gettingStarted'] = time
    }
  }
  _getSongTime(gameTime) {
    return (
      formatTime(Math.min(this._duration, Math.max(0, gameTime))) +
      ' / ' +
      formatTime(this._duration)
    )
  }
  _getReady(gameState) {
    let f = gameState.readyFraction
    return f > 0.5 ? Math.pow(1 - (f - 0.5) / 0.5, 2) : 0
  }
  _createWrapper({
    backgroundImagePromise,
    video,
    panelPlacement,
    infoPanelPosition,
  }) {
    var $wrapper = $('

')
      .attr('data-panel-placement', panelPlacement)
      .attr('data-info-panel-position', infoPanelPosition)
      .append('

')
      .append(this.view)
    if (backgroundImagePromise) {
      Promise.resolve(backgroundImagePromise).then(image =>
        $wrapper.find('.js-back-image').append(image)
      )
    }
    if (video) {
      this._video = video.element
      this._videoOffset = video.offset
      $(video.element)
        .addClass('game-display--video-bg')
        .appendTo($wrapper)
    }
    return $wrapper[0]
  }
  _createTouchEscapeButton() {
    const touchButtons = document.createElement('div')
    touchButtons.className = 'game-display--touch-buttons is-left'
    this.wrapper.appendChild(touchButtons)
    touchButtons.classList.add('is-visible')
    const addTouchButton = (className, onClick) => {
      let button = createTouchButton(onClick, className)
      touchButtons.appendChild(button)
    }
    addTouchButton('game-display--touch-escape-button', () => this._onEscape())
    addTouchButton('game-display--touch-replay-button', () => this._onReplay())

    const escapeHint = document.createElement('div')
    escapeHint.textContent = 'Click or press Esc to exit the tutorial'
    escapeHint.className = 'game-display--escape-hint'
    this._escapeHint = escapeHint
    touchButtons.appendChild(escapeHint)
  }
  _createFullScreenButton() {
    if (shouldDisableFullScreen() || !screenfull.enabled) {
      return
    }
    const touchButtons = document.createElement('div')
    touchButtons.className = 'game-display--touch-buttons is-visible is-right'
    this.wrapper.appendChild(touchButtons)
    const onClick = () => {
      screenfull.request()
    }
    const button = createTouchButton(
      onClick,
      'game-display--touch-fullscreen-button'
    )
    touchButtons.appendChild(button)
  }
  get context() {
    return this._context
  }
  get view() {
    return this._context.view
  }
  get wrapper() {
    return this._wrapper
  }
}

function createTouchButton(onClick, className) {
  let button = document.createElement('button')
  button.addEventListener(
    'touchstart',
    e => {
      e.stopPropagation()
    },
    true
  )
  button.onclick = e => {
    e.preventDefault()
    onClick()
  }
  button.className = className
  return button
}

export default GameDisplay
<|endoftext|>


<commit_before>import _ from 'lodash';

function as_euros(x) {
  return x ? (x.toFixed(2)) : "0";
}

const all_layouts = {
  proforma: {
    class_name: "proforma",
    title: "Recambios - Proformas",
    table: "[Recambios - Proformas]",
    key_field: 'IDProforma',
    ChangeDate: true,           // Update queries add the ChangeDate = now()
    search: {
      fuzzy: {
        fields: [
          { field:"IDProforma", style:{width:"10%"}, filter:"IDProforma like '%__FIELD__%'", min_num_chars:1 },
          { field:"Empresa",    style:{width:"60%"}, filter:"Empresa like '%__FIELD__%'", min_num_chars:3 }
          //{ field:"ChangeDate", style:{width:"10%"}, filter:"now() - ChangeDate < %__FIELD__%" }
        ],
        title: 'Número de la Proforma'
      },
      exact: {
        filter: "IDProforma = '__FIELD__'"
      },
      recent: {
        filter: "now() - ChangeDate < 5 ORDER BY ChangeDate DESC"      // 5 days
      }
    },
    fields: [
      { field:"IDProforma", type:"text", hint:"# Proforma", read_only:true, style:{ width:"75px"} },
      { field:"dlgIDProforma", type:"db_query_and_update"
             , update_fields: { IDProforma:"IDProforma" } },
      { field:"IDCliente", type:"text", read_only:true, style:{ display:"none"} },
      { field:"Empresa", type:"text", hint:"Nombre de la empresa", style:{ width:"40%"} },
      { field:"dlgIDEmpresa", type:"modal_dialog", layout:"dlg_id_cliente"
             , update_fields:{
                // DB exact search table <=> this table
                "Número cliente":"IDCliente"
              , Empresa:"Empresa"
              , NIF:"NIF"
              , CP:"CP"
              , Calle:"Calle"
              , Poblacion:"Poblacion"
              }
             },
      { field:"NIF", type:"text", hint:"NIF/CIF", style:{ width:"10%"} },
      { type:"separator"} ,
      { field:"Fecha", type:"date", mode:"landscape", hint:"Fecha de Creación", textstyle:{ width:"90px" }, style:{display:"inline-block" } },
      //{ field:"ChangeDate", type:"date", hint:"Fecha de Modificación", textstyle:{ width:"90px" }, style:{display:"inline-block" } },
      { field:"Calle", type:"text", style:{ width:"30%" } },
      { field:"Poblacion", type:"text", style:{ width:"30%" } },
      { field:"CP", type:"text", hint:"CP", style:{ width:"70px" } },
      { field:"IDProvincia", type:"lut", lut:"Provincias.ID", title:"Provincia", hint:"Provincia", style:{ width:"15%" } },
      { type:"separator"},
      { field:"Notas", type:"text", multiLine:true, hint:"Notas adicionales", fullWidth:true, can_be_null:true },
      { field:"details", type:"array_table", layout:"proforma_details"
                       , local:"IDProforma", remote:"IDProforma"
                       }
    ]
  },

  // This is the dialog that popup. It contains a single field, which is in fact a search field + results table
  // with it's own layout
  dlg_id_cliente: {
    title: "Buscar Cliente",
    fields: [
      { field:"SearchEmpresa", type:"db_search", layout:"search_cliente" }
    ]
  },
  search_cliente: {
    table: "[Clientes]",
    key_field: 'Número Cliente',
    search: {
      fuzzy: {
        fields: [
          { field:"[Número Cliente]", style:{width:"10%"}, filter:"[Número Cliente] like '%__FIELD__%'", min_num_chars:1 },
          { field:"Empresa",   style:{width:"80%"}, filter:"Empresa like '%__FIELD__%'", min_num_chars:3 }
        ]
      },
      exact: {
        filter: "[Número Cliente] = __FIELD__"
      },
      return_exact_query: true      // Return the full row when clicking a row
    },
    fields: [
      { field:"[Número Cliente]", type:"text", hint:"# Cliente", read_only:true, style:{ width:"10%"} },
      { field:"Empresa", type:"text", style:{ wdith:"80%" } }
    ]
  },

  proforma_details: {
    key_field: 'ID',
    title: "Details",
    table: "[Recambios - Proformas - Detalles]",
    search: {
      join: {
        filter: "IDProforma = '__FIELD__'"
      }
    },
    fields: [
      { field:"ID", type:"hidden", read_only:true },
      { field:"REF", type:"lut_id", lut:"Recambios.REF", hint:"Referencia", column_style:{width:"60px"} },
      { field:"REF.Name", type:"lut_text", title:"Nombre"
                        , lut:"Recambios.REF", link:"REF", hint:"Referencia"
                        , column_style:{width:"300px"}
                        },
      { field:"Cantidad", type:"number"
                        , column_style:{width:"120px"}
       },
      { field:"EurosUnidad", type:"number", title:"€/Unidad"
                        , column_style:{width:"120px"}
       },
      { field:"SubTotal", type:"computed", className:"currency"
                        , formula:(row)=>{return as_euros(row.Cantidad * row.EurosUnidad);}},
      { field:"Tipo", type:"select", lut:"Proformas.Detail.Tipo", default_value:0
                        , column_style:{width:"60px"}
                        },
      { field:"Delete", type:"action", title:"Borrar" }
     // { field:"Nota", type:"text" }
    ],
    tail_fields: [
      { field:"New", type:"actionNew", title:"New Detail", colSpan:"3" },
      { field:"Total", type:"label" },
      { field:"ComputedTotal", type:"computed", className:"currency", formula:(rows)=>{
          return as_euros(
            _.reduce(rows, (accum,d)=>{
              accum += (d.Cantidad*d.EurosUnidad);
              return accum;
            }, 0)
          );
      }}
    ]
  }
};

// -------------------------------------------------------------------
export function get( name ) {
  return all_layouts[name];
}

// -------------------------------------------------------------------
export function getFieldByname( layout, field_name ) {
  const idx = _.findIndex( layout.fields, (r)=>{ return r.field === field_name; } );
  if( idx >= 0 )
    return layout.fields[idx];
  return undefined;
}

// -------------------------------------------------------------------
export function asYYYYMMDD(dt) {
  var r = (1900 + dt.getYear()) + "/";
  var m = 1 + dt.getMonth();
  var d = dt.getDate();
  if( m < 10 )
    r += "0" + m;
  else
    r += m;
  if( d < 10 )
    r += "/0" + d;
  else
    r += "/" + d;
  return r;
}

// -------------------------------------------------------------------
export function validateDates( layout, obj ) {

  _.each( layout.fields, (f)=>{
    if( f.type === "date") {
      var old_value = obj[ f.field ];
      if( typeof old_value === 'string') {
        //console.log( "Correcting string " + f.field + " date from " + old_value)
        let d = new Date( old_value );
        //console.log( "new date_obj " + d)
        let new_value = asYYYYMMDD( d );
        //console.log( "new_value " + new_value)
        obj[ f.field ] = new_value;
      } else {
        //console.log( "Correcting date " + f.field + " date from " + old_value)
        let d = new Date( old_value );
        let new_value = asYYYYMMDD( d );
        //console.log( "new_value " + new_value)
        obj[ f.field ] = new_value;
      }
    }
  });
}

// -------------------------------------------------------------------
export function getNewEmptyRegister( layout ) {
  var data = {};
  _.each( layout.fields, (f)=>{
    if( f.field ) {
      if( f.type == "date")
        data[f.field] = asYYYYMMDD( new Date() );
      else if( f.type == "array_table")
        data[f.field] = [];
      else if( f.multiLine )
        data[f.field] = "";
      else if( f.type == "lut_text" || f.type =="action")
        return;
      else
        data[f.field] = f.default_value;
    }
  });
  return data;
}

<commit_msg>Copy IDProvincia also<commit_after>import _ from 'lodash';

function as_euros(x) {
  return x ? (x.toFixed(2)) : "0";
}

const all_layouts = {
  proforma: {
    class_name: "proforma",
    title: "Recambios - Proformas",
    table: "[Recambios - Proformas]",
    key_field: 'IDProforma',
    ChangeDate: true,           // Update queries add the ChangeDate = now()
    search: {
      fuzzy: {
        fields: [
          { field:"IDProforma", style:{width:"10%"}, filter:"IDProforma like '%__FIELD__%'", min_num_chars:1 },
          { field:"Empresa",    style:{width:"60%"}, filter:"Empresa like '%__FIELD__%'", min_num_chars:3 }
          //{ field:"ChangeDate", style:{width:"10%"}, filter:"now() - ChangeDate < %__FIELD__%" }
        ],
        title: 'Número de la Proforma'
      },
      exact: {
        filter: "IDProforma = '__FIELD__'"
      },
      recent: {
        filter: "now() - ChangeDate < 5 ORDER BY ChangeDate DESC"      // 5 days
      }
    },
    fields: [
      { field:"IDProforma", type:"text", hint:"# Proforma", read_only:true, style:{ width:"75px"} },
      { field:"dlgIDProforma", type:"db_query_and_update"
             , update_fields: { IDProforma:"IDProforma" } },
      { field:"IDCliente", type:"text", read_only:true, style:{ display:"none"} },
      { field:"Empresa", type:"text", hint:"Nombre de la empresa", style:{ width:"40%"} },
      { field:"dlgIDEmpresa", type:"modal_dialog", layout:"dlg_id_cliente"
             , update_fields:{
                // DB exact search table <=> this table
                "Número cliente":"IDCliente"
              , Empresa:"Empresa"
              , NIF:"NIF"
              , CP:"CP"
              , Calle:"Calle"
              , Poblacion:"Poblacion"
              , IDProvincia:"IDProvincia"
              }
             },
      { field:"NIF", type:"text", hint:"NIF/CIF", style:{ width:"10%"} },
      { type:"separator"} ,
      { field:"Fecha", type:"date", mode:"landscape", hint:"Fecha de Creación", textstyle:{ width:"90px" }, style:{display:"inline-block" } },
      //{ field:"ChangeDate", type:"date", hint:"Fecha de Modificación", textstyle:{ width:"90px" }, style:{display:"inline-block" } },
      { field:"Calle", type:"text", style:{ width:"30%" } },
      { field:"Poblacion", type:"text", style:{ width:"30%" } },
      { field:"CP", type:"text", hint:"CP", style:{ width:"70px" } },
      { field:"IDProvincia", type:"lut", lut:"Provincias.ID", title:"Provincia", hint:"Provincia", style:{ width:"15%" } },
      { type:"separator"},
      { field:"Notas", type:"text", multiLine:true, hint:"Notas adicionales", fullWidth:true, can_be_null:true },
      { field:"details", type:"array_table", layout:"proforma_details"
                       , local:"IDProforma", remote:"IDProforma"
                       }
    ]
  },

  // This is the dialog that popup. It contains a single field, which is in fact a search field + results table
  // with it's own layout
  dlg_id_cliente: {
    title: "Buscar Cliente",
    fields: [
      { field:"SearchEmpresa", type:"db_search", layout:"search_cliente" }
    ]
  },
  search_cliente: {
    table: "[Clientes]",
    key_field: 'Número Cliente',
    search: {
      fuzzy: {
        fields: [
          { field:"[Número Cliente]", style:{width:"10%"}, filter:"[Número Cliente] like '%__FIELD__%'", min_num_chars:1 },
          { field:"Empresa",   style:{width:"80%"}, filter:"Empresa like '%__FIELD__%'", min_num_chars:3 }
        ]
      },
      exact: {
        filter: "[Número Cliente] = __FIELD__"
      },
      return_exact_query: true      // Return the full row when clicking a row
    },
    fields: [
      { field:"[Número Cliente]", type:"text", hint:"# Cliente", read_only:true, style:{ width:"10%"} },
      { field:"Empresa", type:"text", style:{ wdith:"80%" } }
    ]
  },

  proforma_details: {
    key_field: 'ID',
    title: "Details",
    table: "[Recambios - Proformas - Detalles]",
    search: {
      join: {
        filter: "IDProforma = '__FIELD__'"
      }
    },
    fields: [
      { field:"ID", type:"hidden", read_only:true },
      { field:"REF", type:"lut_id", lut:"Recambios.REF", hint:"Referencia", column_style:{width:"60px"} },
      { field:"REF.Name", type:"lut_text", title:"Nombre"
                        , lut:"Recambios.REF", link:"REF", hint:"Referencia"
                        , column_style:{width:"300px"}
                        },
      { field:"Cantidad", type:"number"
                        , column_style:{width:"120px"}
       },
      { field:"EurosUnidad", type:"number", title:"€/Unidad"
                        , column_style:{width:"120px"}
       },
      { field:"SubTotal", type:"computed", className:"currency"
                        , formula:(row)=>{return as_euros(row.Cantidad * row.EurosUnidad);}},
      { field:"Tipo", type:"select", lut:"Proformas.Detail.Tipo", default_value:0
                        , column_style:{width:"60px"}
                        },
      { field:"Delete", type:"action", title:"Borrar" }
     // { field:"Nota", type:"text" }
    ],
    tail_fields: [
      { field:"New", type:"actionNew", title:"New Detail", colSpan:"3" },
      { field:"Total", type:"label" },
      { field:"ComputedTotal", type:"computed", className:"currency", formula:(rows)=>{
          return as_euros(
            _.reduce(rows, (accum,d)=>{
              accum += (d.Cantidad*d.EurosUnidad);
              return accum;
            }, 0)
          );
      }}
    ]
  }
};

// -------------------------------------------------------------------
export function get( name ) {
  return all_layouts[name];
}

// -------------------------------------------------------------------
export function getFieldByname( layout, field_name ) {
  const idx = _.findIndex( layout.fields, (r)=>{ return r.field === field_name; } );
  if( idx >= 0 )
    return layout.fields[idx];
  return undefined;
}

// -------------------------------------------------------------------
export function asYYYYMMDD(dt) {
  var r = (1900 + dt.getYear()) + "/";
  var m = 1 + dt.getMonth();
  var d = dt.getDate();
  if( m < 10 )
    r += "0" + m;
  else
    r += m;
  if( d < 10 )
    r += "/0" + d;
  else
    r += "/" + d;
  return r;
}

// -------------------------------------------------------------------
export function validateDates( layout, obj ) {

  _.each( layout.fields, (f)=>{
    if( f.type === "date") {
      var old_value = obj[ f.field ];
      if( typeof old_value === 'string') {
        //console.log( "Correcting string " + f.field + " date from " + old_value)
        let d = new Date( old_value );
        //console.log( "new date_obj " + d)
        let new_value = asYYYYMMDD( d );
        //console.log( "new_value " + new_value)
        obj[ f.field ] = new_value;
      } else {
        //console.log( "Correcting date " + f.field + " date from " + old_value)
        let d = new Date( old_value );
        let new_value = asYYYYMMDD( d );
        //console.log( "new_value " + new_value)
        obj[ f.field ] = new_value;
      }
    }
  });
}

// -------------------------------------------------------------------
export function getNewEmptyRegister( layout ) {
  var data = {};
  _.each( layout.fields, (f)=>{
    if( f.field ) {
      if( f.type == "date")
        data[f.field] = asYYYYMMDD( new Date() );
      else if( f.type == "array_table")
        data[f.field] = [];
      else if( f.multiLine )
        data[f.field] = "";
      else if( f.type == "lut_text" || f.type =="action")
        return;
      else
        data[f.field] = f.default_value;
    }
  });
  return data;
}

<|endoftext|>