<commit_before>var ctr = 0;
var item = {
  keys: [new key(ctr,"#000","Thing " + (ctr+1))],
  time: [],
  interval: 1000
}
function key(i,c,d) {
  this.ID = "i" + i;
  this.color = c;
  this.desc = d;
  ctr++;
}
function drawResults() {
  $('#out').empty();
  var list = item.time;
  for (i in list) {
    $('#out').append("

");
  }
  curr = (item.time.length);
  $("#undo button, #log").text(curr);
}
var curr = 0;
function loadItem() {
    var url = window.location.href;
    var data = url.slice(url.indexOf('?')+1).split('&');
    for (d in data) {
        var loc = data[d].indexOf('q=');
        if (loc >= 0) {
            var q = data[d].substring(loc+2);
            item = JSON.parse(decodeURIComponent(q));
        }
    }
    drawResults();
}
loadItem();

// clicking a plus
$("#in").on('click','#add',function() {
  var c = Math.floor(Math.random()*16777216).toString(16);
  if (c.length != 6) { c = "#0" + c; }
  else { c = "#" + c; }
  $("#in").append("
" +
                    "<input id='color' type='color' " +
                    "value='" + c + "'> " +
                    "<input id='desc' value='Thing " + (ctr+1) + "'> " +
                    "<button id='add'></button> " +
                    "<button id='del'></button >" +
                    "<button id='log'>X</log>" +
                  "
");
  item.keys.push(new key(ctr,c,"Thing " + (ctr+1)));
});

// clicking a minus
$("#in").on('click','#del',function() {
  var id = $(this).parent().attr("id");
  for (i in item.keys) {
    if (item.keys[i].ID == id) {
      item.keys.splice(i,1);
    }
  }
  $("#"+id).remove();
});

// changing an input
$("#in").on('change','input',function() {
  var pt = $(this).parent();
  var pid = pt.attr('id');
  var mid = $(this).attr('id');
  for (x in item.keys) {
    if (item.keys[x].ID == pid && mid == 'desc') {
      console.log(pid+"'s desc was changed");
      item.keys[x].desc = $(this).val();
    }
    else if (item.keys[x].ID == pid && mid == 'color') {
      console.log(pid+"'s color was changed");
      item.keys[x].color = $(this).val();
    }
  }
});

// lock activities and start
$("#lock").click(function() {
  $(".lock, #add, #log, #undo").toggle();
  $("#add, #del").hide();
  $("input").attr('disabled',true);
});

// unlock activities and pause
$("#unlock").click(function() {
  $(".lock, #add, #log, #undo").toggle();
  $("input").attr('disabled',false);
});

// add event pressed
$("#in").on('click','#log',function() {
  var pid = $(this).parent().attr('id');
  var list = item.time;
  for (x in item.keys) {
    if (item.keys[x].ID == pid) {
      list.splice(curr,0,item.keys[x]);
    }
  }
  drawResults();
});

// undo event
$("#undo").click(function() {
  item.time.splice(parseInt(curr)-1,1);
  drawResults();
});

// click an event
$("#out").on('click','div',function() {
  curr = parseInt($(this).attr('data-id'))+1;
  $("#undo button, #log").text(curr);
});<commit_msg>ctr, len<commit_after>var ctr = 0;
var item = {
  keys: [new key(ctr,"#000","Thing " + (ctr+1))],
  time: [],
  interval: 1000
}
function key(i,c,d) {
  this.ID = "i" + i;
  this.color = c;
  this.desc = d;
  ctr++;
}
function drawResults() {
  $('#out').empty();
  var list = item.time;
  for (i in list) {
    $('#out').append("

");
  }
  curr = (item.time.length);
  $("#undo button, #log").text(curr);
}
var curr = 0;
function loadItem() {
    var url = window.location.href;
    var data = url.slice(url.indexOf('?')+1).split('&');
    for (d in data) {
        var loc = data[d].indexOf('q=');
        if (loc >= 0) {
            var q = data[d].substring(loc+2);
            item = JSON.parse(decodeURIComponent(q));
            ctr = parseInt(item.keys[item.keys.length-1].ID.substring(1))+1;
        }
    }
    drawResults();
}
loadItem();

// clicking a plus
$("#in").on('click','#add',function() {
  var c = Math.floor(Math.random()*16777216).toString(16);
  if (c.length != 6) { c = "#0" + c; }
  else { c = "#" + c; }
  $("#in").append("
" +
                    "<input id='color' type='color' " +
                    "value='" + c + "'> " +
                    "<input id='desc' value='Thing " + (ctr+1) + "'> " +
                    "<button id='add'></button> " +
                    "<button id='del'></button >" +
                    "<button id='log'>X</log>" +
                  "
");
  var len = item.keys.length;
  item.keys.push(new key(ctr,c,"Thing " + (ctr+1)));
});

// clicking a minus
$("#in").on('click','#del',function() {
  var id = $(this).parent().attr("id");
  for (i in item.keys) {
    if (item.keys[i].ID == id) {
      item.keys.splice(i,1);
    }
  }
  $("#"+id).remove();
});

// changing an input
$("#in").on('change','input',function() {
  var pt = $(this).parent();
  var pid = pt.attr('id');
  var mid = $(this).attr('id');
  for (x in item.keys) {
    if (item.keys[x].ID == pid && mid == 'desc') {
      console.log(pid+"'s desc was changed");
      item.keys[x].desc = $(this).val();
    }
    else if (item.keys[x].ID == pid && mid == 'color') {
      console.log(pid+"'s color was changed");
      item.keys[x].color = $(this).val();
    }
  }
});

// lock activities and start
$("#lock").click(function() {
  $(".lock, #add, #log, #undo").toggle();
  $("#add, #del").hide();
  $("input").attr('disabled',true);
});

// unlock activities and pause
$("#unlock").click(function() {
  $(".lock, #add, #log, #undo").toggle();
  $("input").attr('disabled',false);
});

// add event pressed
$("#in").on('click','#log',function() {
  var pid = $(this).parent().attr('id');
  var list = item.time;
  for (x in item.keys) {
    if (item.keys[x].ID == pid) {
      list.splice(curr,0,item.keys[x]);
    }
  }
  drawResults();
});

// undo event
$("#undo").click(function() {
  item.time.splice(parseInt(curr)-1,1);
  drawResults();
});

// click an event
$("#out").on('click','div',function() {
  curr = parseInt($(this).attr('data-id'))+1;
  $("#undo button, #log").text(curr);
});<|endoftext|>


<commit_before>const rootVm = new Vue({
    el: '#app-sudoku',
    template: `

 event.target.focus()"
    >

                        {{ cell.value }}
                        {{ cell.value }}

 set ? i + 1 : ''))">
                            {{ n }}

        <historical-event :event="command" :key="index" :active="history.commands.length - index === history.current"
        v-for="(command, index) in Array.from(history.commands).reverse()" />

initial

`,
    components: {
        'historical-event': {
            props: { event: Object, active: Boolean, },
            template: '
{{ where + " " + what }}
',
            computed: {
                where: function() {
                    const where = this.event.where;
                    return '(' + (~~(where / 9) + 1) + ',' + (where % 9 + 1) + ')';
                },
                what: function() {
                    switch(this.event.type) {
                    case 'erase': return 'erase';
                    default: return this.event.type + ' ' + this.event.value;
                    }
                },
            },
        }
    },
    computed: {
        affectedIndices: function() { return this.affectedIndicesBy(this.pointed); },
        boxes: function() {
            return this.chunksOf(9, this.indices.box.map(index => this.cells[index]));
        },
        cells: function() {
            /* manage each number cell by the object: {
                {Boolean} given, -- true if the number is given for clue, otherwise false.
                {Number} value, -- a number between 0 to 9.
                {Array} memo, -- array of Boolean, each element represent the number those of which can be placed, user considers.
            } */
            const initial = Array.from(
                '060003001200500600007090500000400090800000006010005000002010700004009003700200040' // 朝日新聞beパズル 2017/10/07 掲載分
            ).map(Number).map(n => new Object({given: Boolean(n), value: n, memo: Array(9), }));
            const commands = this.history.commands.slice(0, this.history.current);
            return commands.reduce((board, command) => {
                const target = board[command.where];
                switch(command.type) {
                case 'place':
                case 'erase':
                    target.value = command.value;
                    break;
                case 'remark':
                case 'unmark':
                    target.memo[command.value - 1] = command.type[0] === 'r';
                    break;
                case 'flush':
                    this.affectedIndicesBy(command.where).forEach(index => board[index].memo[command.value - 1] = false);
                    break;
                }
                return board;
            }, initial);
        },
        missPlacedIndices: function() {
            const unique = (value, index, array) => array.indexOf(value) === index;
            const indices = [this.indices.row, this.indices.col, this.indices.box].reduce((a, b) => a.concat(b));
            const dupOrNot = this.chunksOf(9, indices.map(index => this.cells[index].value)) // for each 9...
            .map(vs => vs.map((v, i, self) => v && self.slice(0, i).concat(self.slice(i+1)).some(x => x === v))) // flag non-zero and duplicates
            .reduce((a, b) => a.concat(b));
            return dupOrNot.map((v, i) => v ? indices[i] : NaN).filter(unique); // NaN will be removed by unique.
        },
        indices: (() => {
            const colNr = index => index % 9;
            const boxNr = index => 3 * ~~(index / 27) + ~~((index % 9) / 3);
            const row = Array.from({length: 81, }).map((_, index) => index);
            const col = Array.from(row).sort((a, b) => colNr(a) - colNr(b));
            const box = Array.from(row).sort((a, b) => boxNr(a) - boxNr(b));
            const indices = { row: row, col: col, box: box, };
            return () => indices;
        })(),
        pointedCell: function() { return this.cells[this.pointed] || {given: true, }; },
    },
    data: () => new Object({
        pointed: -1,
        /* user operations. this backs undo/redo up.
        `current` points `commands` array index where new command to be inserted into. */
        history: {commands: [], current: 0, },
    }),
    methods: {
        chunksOf: (() => {
            const splitAt = (array, n) => [array.slice(0, n), array.slice(n)];
            const reduceConcat = a => a.length ? a.reduce((a, b) => [a].concat(reduceConcat(b))) : [];

            return (n, array) => {
                const splitted = splitAt(array, n);
                var p = splitted;
                while (p[1].length !== 0) {
                    p[1] = splitAt(p[1], n);
                    p = p[1];
                }
                return reduceConcat(splitted);
            };
        })(),
        affectedIndicesBy: function(cellIndex) {
            const get = array => {
                const index = array.findIndex(x => x === cellIndex);
                const start = 9 * ~~(index / 9);
                return array.slice(start, start + (index !== -1 ? 9 : 0));
            };
            return [get(this.indices.row), get(this.indices.col), get(this.indices.box)]
            .reduce((a, b) => a.concat(b)) // flatten array
            .filter(value => value !== cellIndex) // remove cellIndex itself
            .filter((value, index, array) => array.indexOf(value) === index); // remove duplicates
        },
        onKey: function(event) {
            const ALT = event.altKey;
            const SHIFT = event.shiftKey;
            const NUMBER = Number((/^Digit([1-9])$/.exec(event.code) || [])[1]);
            const UNDO = event.code === 'KeyZ' && ALT && !SHIFT;
            const REDO = (event.code === 'KeyZ' && ALT && SHIFT) || (event.code === 'KeyY' && ALT && !SHIFT);
            if (ALT && NUMBER && this.pointed !== -1) {
                this.mark(NUMBER, !SHIFT);
            } else if (!ALT && NUMBER && !this.pointedCell.given) {
                this.place(NUMBER);
            } else if (['Digit0', 'Backspace'].includes(event.code) && !this.pointedCell.given) {
                this.erase();
            } else if (UNDO && this.history.current !== 0) {
                this.history.current -= 1;
            } else if (REDO && this.history.current != this.history.commands.length) {
                this.history.current += 1;
            }
        },
        place: function(number) {
            this.push({value: number, type: 'place', });
        },
        erase: function() {
            this.push({value: 0, type: 'erase', });
        },
        mark: function(number, mark) {
            this.push({value: number, type: mark ? 'remark' : 'unmark', });
        },
        flush: function() {
            this.push({value: this.pointedCell.value, type: 'flush', });
        },
        push: function(command) {
            this.history.commands.splice(this.history.current ++, Infinity,
                Object.assign({when: new Date(), where: this.pointed, }, command));
        },
    },
});
<commit_msg>Rewrite `chunksOf` using iterator protocol.<commit_after>const rootVm = new Vue({
    el: '#app-sudoku',
    template: `

 event.target.focus()"
    >

                        {{ cell.value }}
                        {{ cell.value }}

 set ? i + 1 : ''))">
                            {{ n }}

        <historical-event :event="command" :key="index" :active="history.commands.length - index === history.current"
        v-for="(command, index) in Array.from(history.commands).reverse()" />

initial

`,
    components: {
        'historical-event': {
            props: { event: Object, active: Boolean, },
            template: '
{{ where + " " + what }}
',
            computed: {
                where: function() {
                    const where = this.event.where;
                    return '(' + (~~(where / 9) + 1) + ',' + (where % 9 + 1) + ')';
                },
                what: function() {
                    switch(this.event.type) {
                    case 'erase': return 'erase';
                    default: return this.event.type + ' ' + this.event.value;
                    }
                },
            },
        }
    },
    computed: {
        affectedIndices: function() { return this.affectedIndicesBy(this.pointed); },
        boxes: function() {
            return this.chunksOf(9, this.indices.box.map(index => this.cells[index]));
        },
        cells: function() {
            /* manage each number cell by the object: {
                {Boolean} given, -- true if the number is given for clue, otherwise false.
                {Number} value, -- a number between 0 to 9.
                {Array} memo, -- array of Boolean, each element represent the number those of which can be placed, user considers.
            } */
            const initial = Array.from(
                '060003001200500600007090500000400090800000006010005000002010700004009003700200040' // 朝日新聞beパズル 2017/10/07 掲載分
            ).map(Number).map(n => new Object({given: Boolean(n), value: n, memo: Array(9), }));
            const commands = this.history.commands.slice(0, this.history.current);
            return commands.reduce((board, command) => {
                const target = board[command.where];
                switch(command.type) {
                case 'place':
                case 'erase':
                    target.value = command.value;
                    break;
                case 'remark':
                case 'unmark':
                    target.memo[command.value - 1] = command.type[0] === 'r';
                    break;
                case 'flush':
                    this.affectedIndicesBy(command.where).forEach(index => board[index].memo[command.value - 1] = false);
                    break;
                }
                return board;
            }, initial);
        },
        missPlacedIndices: function() {
            const unique = (value, index, array) => array.indexOf(value) === index;
            const indices = [this.indices.row, this.indices.col, this.indices.box].reduce((a, b) => a.concat(b));
            const dupOrNot = this.chunksOf(9, indices.map(index => this.cells[index].value)) // for each 9...
            .map(vs => vs.map((v, i, self) => v && self.slice(0, i).concat(self.slice(i+1)).some(x => x === v))) // flag non-zero and duplicates
            .reduce((a, b) => a.concat(b));
            return dupOrNot.map((v, i) => v ? indices[i] : NaN).filter(unique); // NaN will be removed by unique.
        },
        indices: (() => {
            const colNr = index => index % 9;
            const boxNr = index => 3 * ~~(index / 27) + ~~((index % 9) / 3);
            const row = Array.from({length: 81, }).map((_, index) => index);
            const col = Array.from(row).sort((a, b) => colNr(a) - colNr(b));
            const box = Array.from(row).sort((a, b) => boxNr(a) - boxNr(b));
            const indices = { row: row, col: col, box: box, };
            return () => indices;
        })(),
        pointedCell: function() { return this.cells[this.pointed] || {given: true, }; },
    },
    data: () => new Object({
        pointed: -1,
        /* user operations. this backs undo/redo up.
        `current` points `commands` array index where new command to be inserted into. */
        history: {commands: [], current: 0, },
    }),
    methods: {
        chunksOf: (n, array) => {
            const chunks = {};
            chunks[Symbol.iterator] = () => {
                var i = 0;
                return { next: () => new Object({done: i >= array.length, value: array.slice(i, i += n), }), };
            };
            return Array.from(chunks);
        },
        affectedIndicesBy: function(cellIndex) {
            const get = array => {
                const index = array.findIndex(x => x === cellIndex);
                const start = 9 * ~~(index / 9);
                return array.slice(start, start + (index !== -1 ? 9 : 0));
            };
            return [get(this.indices.row), get(this.indices.col), get(this.indices.box)]
            .reduce((a, b) => a.concat(b)) // flatten array
            .filter(value => value !== cellIndex) // remove cellIndex itself
            .filter((value, index, array) => array.indexOf(value) === index); // remove duplicates
        },
        onKey: function(event) {
            const ALT = event.altKey;
            const SHIFT = event.shiftKey;
            const NUMBER = Number((/^Digit([1-9])$/.exec(event.code) || [])[1]);
            const UNDO = event.code === 'KeyZ' && ALT && !SHIFT;
            const REDO = (event.code === 'KeyZ' && ALT && SHIFT) || (event.code === 'KeyY' && ALT && !SHIFT);
            if (ALT && NUMBER && this.pointed !== -1) {
                this.mark(NUMBER, !SHIFT);
            } else if (!ALT && NUMBER && !this.pointedCell.given) {
                this.place(NUMBER);
            } else if (['Digit0', 'Backspace'].includes(event.code) && !this.pointedCell.given) {
                this.erase();
            } else if (UNDO && this.history.current !== 0) {
                this.history.current -= 1;
            } else if (REDO && this.history.current != this.history.commands.length) {
                this.history.current += 1;
            }
        },
        place: function(number) {
            this.push({value: number, type: 'place', });
        },
        erase: function() {
            this.push({value: 0, type: 'erase', });
        },
        mark: function(number, mark) {
            this.push({value: number, type: mark ? 'remark' : 'unmark', });
        },
        flush: function() {
            this.push({value: this.pointedCell.value, type: 'flush', });
        },
        push: function(command) {
            this.history.commands.splice(this.history.current ++, Infinity,
                Object.assign({when: new Date(), where: this.pointed, }, command));
        },
    },
});
<|endoftext|>


<commit_before>import { addOnceEventListener } from '../util/helpers'

export default {
  data () {
    return {
      overlay: null
    }
  },

  props: {
    hideOverlay: Boolean
  },

  methods: {
    genOverlay () {
      if (!this.isActive) return

      const overlay = document.createElement('div')
      overlay.className = 'overlay'
      if (this.absolute) overlay.className += ' overlay--absolute'

      this.$el.parentNode.insertBefore(overlay, this.$el.nextSibling)

      setTimeout(() => {
        overlay.className += ' overlay--active'
        this.overlay = overlay
      }, 0)
    },
    removeOverlay () {
      if (!this.overlay) return

      addOnceEventListener(this.overlay, 'transitionend', () => {
        this.overlay && this.overlay.remove()
        this.overlay = null
      })

      this.overlay.className = this.overlay.className.replace('overlay--active', '')
    }
  }
}
<commit_msg>fix for #571 added check for hide-overlay prop<commit_after>import { addOnceEventListener } from '../util/helpers'

export default {
  data () {
    return {
      overlay: null
    }
  },

  props: {
    hideOverlay: Boolean
  },

  methods: {
    genOverlay () {
      if (!this.isActive || this.hideOverlay) return

      const overlay = document.createElement('div')
      overlay.className = 'overlay'
      if (this.absolute) overlay.className += ' overlay--absolute'

      this.$el.parentNode.insertBefore(overlay, this.$el.nextSibling)

      setTimeout(() => {
        overlay.className += ' overlay--active'
        this.overlay = overlay
      }, 0)
    },
    removeOverlay () {
      if (!this.overlay) return

      addOnceEventListener(this.overlay, 'transitionend', () => {
        this.overlay && this.overlay.remove()
        this.overlay = null
      })

      this.overlay.className = this.overlay.className.replace('overlay--active', '')
    }
  }
}
<|endoftext|>


<commit_before>  function Input(options)
  {
    $.extend(true, this, {
    }, options);

    var actions = { }
    var bounds = {}
    var active_actions = {}

    var nice_name = function(e)
    {
      var result = jQuery.hotkeys.specialKeys[e.which]
      if (result != undefined)
        return result
      return String.fromCharCode(e.which).toLowerCase()
    }

    $(document).bind("keydown", function(e)
    {
      var action = bounds[nice_name(e)]

      if (action == undefined)
        return

      e.preventDefault();

      active_actions[action] = $.merge([], actions[action].cb)
    });

    $(document).bind("keyup", function(e)
    {
      var action = bounds[nice_name(e)]

      if (action == undefined)
        return

      e.preventDefault();

      delete active_actions[action]
    });

    this.register_action = function(action_name, default_bound, cb)
    {
      actions[action_name] = {
        bound: default_bound,
        cb: [],
      }
      var all_bound = default_bound.split(" ")
      $.each(all_bound, function(i, bound)
      {
        if (bound)
          bounds[bound] = action_name
      })

      if ($.isFunction(cb))
      {
        this.add_action(action_name, cb)
      }
    }
    this.add_action = function(added_action, cb)
    {
      var action = actions[added_action]
      if (action == undefined)
        return

      action.cb.push(cb)
    }

    this.frame = function()
    {
      $.each(active_actions, function(action, cbs)
      {
        $.each(cbs, function(i, cb)
        {
          if (!$.isFunction(cb))
            return

          var result = cb()
          if (result === false)
          {
            delete cbs[i]
          }
        })
      })
    }

    this.register_action("right", "right")
    this.register_action("left",  "left")
    this.register_action("jump",  "space up")
    this.register_action("atk_pri", "x")
    this.register_action("atk_sec", "z")

  }

  [% IF engine_input %]
  $(function()
  {
    input.register_action('force_up', 'a', function()
    {
      user.y += 2;
    })
    input.register_action('force_down', 'shift+a', function()
    {
      user.y -= 2;
    })

    input.register_action('show_frame', 't', function()
    {
      console.log('t');
      runtime_frame();
    })

    input.register_action('show_all_phys', 'y', function()
    {
      //all_physics.pop()
      console.log(all_physics)
    })

    input.register_action('remove_last_phys', 'shift+y', function()
    {
      all_physics.pop()
      console.log(all_physics)
    })

    input.register_action('start_runtime','shift+q `', function()
    {
      start_runtime()
    })

    input.register_action('stop_runtime', 'q esc', function()
    {
      stop_runtime()
    })

    input.register_action('zoom_out', '-', function()
    {
      zoom = zoom / 2
      console.log(zoom)
    })

    input.register_action('zoom_in', '+', function()
    {
      zoom = zoom * 2
      console.log(zoom)
    })

    input.register_action('trans_l', 'h', function()
    {
      trans_x -= 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_r', 'l', function()
    {
      trans_x += 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_d', 'j', function()
    {
      trans_y -= 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_u', 'k', function()
    {
      trans_y += 200
      console.log(trans_x, trans_y)
    })

  })
  [% END %]
<commit_msg>Improve Input to include alt, ctrl and shift. Those don't 100% work yet<commit_after>  function Input(options)
  {
    $.extend(true, this, {
    }, options);

    var actions = { }
    var bounds = {}
    var active_actions = {}

    var special_keys = {
      8:  "backspace", 9:  "tab",   13: "return", 16: "shift",
      17: "ctrl",      18: "alt",   19: "pause",  20: "capslock",
      27: "esc",       32: "space", 33: "pageup", 34: "pagedown",
      35: "end",       36: "home",  37: "left",   38: "up",
      39: "right",     40: "down",  45: "insert", 46: "del",

      96:  "0", 97:  "1", 98:  "2", 99:  "3", 100: "4",
      101: "5", 102: "6", 103: "7", 104: "8", 105: "9",
      106: "*", 107: "+", 109: "-", 110: ".", 111: "/",

      112: "f1", 113: "f2",  114: "f3",  115: "f4",
      116: "f5", 117: "f6",  118: "f7",  119: "f8",
      120: "f9", 121: "f10", 122: "f11", 123: "f12",

      144: "numlock", 145: "scroll", 191: "/", 192: '`',
      224: "meta",
    }

    var nice_name = function(e)
    {
      var key = special_keys[e.which] || String.fromCharCode(e.which)
      key = key.toLowerCase()

      var keys = [ key ];

      if (e.altKey && key != "alt")
        keys.unshift("alt")
      if (e.ctrlKey && key != "ctrl")
        keys.unshift("ctrl")
      if (e.shiftKey && key != "shift")
        keys.unshift("shift")

      //console.log(e.type, e.which, keys.join('+'))
      return keys.join('+');
    }

    $(document).bind("keydown", function(e)
    {
      var action = bounds[nice_name(e)]

      if (action == undefined)
        return

      e.preventDefault();

      active_actions[action] = $.merge([], actions[action].cb)
    });

    $(document).bind("keyup", function(e)
    {
      var action = bounds[nice_name(e)]

      if (action == undefined)
        return

      e.preventDefault();

      delete active_actions[action]
    });

    this.register_action = function(action_name, default_bound, cb)
    {
      actions[action_name] = {
        bound: default_bound,
        cb: [],
      }
      var all_bound = default_bound.split(" ")
      $.each(all_bound, function(i, bound)
      {
        if (bound)
        {
          var modifiers = bound.split("+")
          var key = modifiers.pop()
          modifiers.sort().push(key)
          bound = modifiers.join("+")
          //console.log(bound, action_name)
          bounds[bound] = action_name
        }
      })

      if ($.isFunction(cb))
      {
        this.add_action(action_name, cb)
      }
    }
    this.add_action = function(added_action, cb)
    {
      var action = actions[added_action]
      if (action == undefined)
        return

      action.cb.push(cb)
    }

    this.frame = function()
    {
      $.each(active_actions, function(action, cbs)
      {
        $.each(cbs, function(i, cb)
        {
          if (!$.isFunction(cb))
            return

          var result = cb()
          if (result === false)
          {
            delete cbs[i]
          }
        })
      })
    }

    this.register_action("right", "right")
    this.register_action("left",  "left")
    this.register_action("jump",  "space up")
    this.register_action("atk_pri", "x")
    this.register_action("atk_sec", "z")

  }

  [% IF engine_input %]
  $(function()
  {
    input.register_action('force_up', 'a', function()
    {
      user.y += 2;
    })
    input.register_action('force_down', 'shift+a', function()
    {
      user.y -= 2;
    })

    input.register_action('show_frame', 't', function()
    {
      console.log('t');
      runtime_frame();
    })

    input.register_action('show_all_phys', 'y', function()
    {
      //all_physics.pop()
      console.log(all_physics)
    })

    input.register_action('remove_last_phys', 'shift+y', function()
    {
      all_physics.pop()
      console.log(all_physics)
    })

    input.register_action('start_runtime','shift+q `', function()
    {
      start_runtime()
    })

    input.register_action('stop_runtime', 'q esc', function()
    {
      stop_runtime()
    })

    input.register_action('zoom_out', '-', function()
    {
      zoom = zoom / 2
      console.log(zoom)
    })

    input.register_action('zoom_in', '+', function()
    {
      zoom = zoom * 2
      console.log(zoom)
    })

    input.register_action('trans_l', 'h', function()
    {
      trans_x -= 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_r', 'l', function()
    {
      trans_x += 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_d', 'j', function()
    {
      trans_y -= 200
      console.log(trans_x, trans_y)
    })

    input.register_action('trans_u', 'k', function()
    {
      trans_y += 200
      console.log(trans_x, trans_y)
    })

  })
  [% END %]
<|endoftext|>


<commit_before>module("queue", { teardown: moduleTeardown });

test("queue() with other types",function() {
	expect(12);
	var counter = 0;

	stop();

	var $div = jQuery({}),
		defer;

	$div.promise("foo").done(function() {
		equal( counter, 0, "Deferred for collection with no queue is automatically resolved" );
	});

	$div
		.queue("foo",function(){
			equal( ++counter, 1, "Dequeuing" );
			jQuery.dequeue(this,"foo");
		})
		.queue("foo",function(){
			equal( ++counter, 2, "Dequeuing" );
			jQuery(this).dequeue("foo");
		})
		.queue("foo",function(){
			equal( ++counter, 3, "Dequeuing" );
		})
		.queue("foo",function(){
			equal( ++counter, 4, "Dequeuing" );
		});

	defer = $div.promise("foo").done(function() {
		equal(  counter, 4, "Testing previous call to dequeue in deferred"  );
		start();
	});

	equal( $div.queue("foo").length, 4, "Testing queue length" );

	equal( $div.queue("foo", undefined).queue("foo").length, 4, ".queue('name',undefined) does nothing but is chainable (#5571)");

	$div.dequeue("foo");

	equal( counter, 3, "Testing previous call to dequeue" );
	equal( $div.queue("foo").length, 1, "Testing queue length" );

	$div.dequeue("foo");

	equal( counter, 4, "Testing previous call to dequeue" );
	equal( $div.queue("foo").length, 0, "Testing queue length" );
});

test("queue(name) passes in the next item in the queue as a parameter", function() {
	expect(2);

	var div = jQuery({});
	var counter = 0;

	div.queue("foo", function(next) {
		equal(++counter, 1, "Dequeueing");
		next();
	}).queue("foo", function(next) {
		equal(++counter, 2, "Next was called");
		next();
	}).queue("bar", function() {
		equal(++counter, 3, "Other queues are not triggered by next()")
	});

	div.dequeue("foo");
});

test("queue() passes in the next item in the queue as a parameter to fx queues", function() {
	expect(3);
	stop();

	var div = jQuery({});
	var counter = 0;

	div.queue(function(next) {
		equal(++counter, 1, "Dequeueing");
		var self = this;
		setTimeout(function() { next() }, 500);
	}).queue(function(next) {
		equal(++counter, 2, "Next was called");
		next();
	}).queue("bar", function() {
		equal(++counter, 3, "Other queues are not triggered by next()")
	});

	jQuery.when( div.promise("fx"), div ).done(function() {
		equal(counter, 2, "Deferreds resolved");
		start();
	});
});

test("callbacks keep their place in the queue", function() {
	expect(5);
	stop();
	var div = jQuery("<div>"),
		counter = 0;

	div.queue(function( next ) {
		equal( ++counter, 1, "Queue/callback order: first called" );
		setTimeout( next, 200 );
	}).show(100, function() {
		equal( ++counter, 2, "Queue/callback order: second called" );
		jQuery(this).hide(100, function() {
			equal( ++counter, 4, "Queue/callback order: fourth called" );
		});
	}).queue(function( next ) {
		equal( ++counter, 3, "Queue/callback order: third called" );
		next();
	});

	div.promise("fx").done(function() {
		equal(counter, 4, "Deferreds resolved");
		jQuery.removeData( div[0], "olddisplay", true );
		start();
	});
});

test("delay()", function() {
	expect(2);
	stop();

	var foo = jQuery({}), run = 0;

	foo.delay(100).queue(function(){
		run = 1;
		ok( true, "The function was dequeued." );
		start();
	});

	equal( run, 0, "The delay delayed the next function from running." );
});

test("delay() can be stopped", function() {
	expect( 3 );
	stop();

	var foo = jQuery({}), run = 0;

	foo
		.queue( "alternate", function( next ) {
			run++;
			ok( true, "This first function was dequeued" );
			next();
		})
		.delay( 100, "alternate" )
		.queue( "alternate", function() {
			run++;
			ok( true, "The function was dequeued immediately, the delay was stopped" );
		})
		.dequeue( "alternate" )

		// stop( "alternate", false ) will NOT clear the queue, so it should automatically dequeue the next
		.stop( "alternate", false, false )

		// this test
		.delay( 100 )
		.queue(function() {
			run++;
			ok( false, "This queue should never run" );
		})

		// stop( clearQueue ) should clear the queue
		.stop( true, false );

	equal( run, 2, "Queue ran the proper functions" );

	setTimeout( start, 200 );
});

test("clearQueue(name) clears the queue", function() {
	expect(2);

	stop()

	var div = jQuery({});
	var counter = 0;

	div.queue("foo", function(next) {
		counter++;
		jQuery(this).clearQueue("foo");
		next();
	}).queue("foo", function(next) {
		counter++;
	});

	div.promise("foo").done(function() {
		ok( true, "dequeue resolves the deferred" );
		start();
	});

	div.dequeue("foo");

	equal(counter, 1, "the queue was cleared");
});

test("clearQueue() clears the fx queue", function() {
	expect(1);

	var div = jQuery({});
	var counter = 0;

	div.queue(function(next) {
		counter++;
		var self = this;
		setTimeout(function() { jQuery(self).clearQueue(); next(); }, 50);
	}).queue(function(next) {
		counter++;
	});

	equal(counter, 1, "the queue was cleared");

	div.removeData();
});

test("_mark() and _unmark()", function() {
	expect(1);

	var div = {},
		$div = jQuery( div );

	stop();

	jQuery._mark( div, "foo" );
	jQuery._mark( div, "foo" );
	jQuery._unmark( div, "foo" );
	jQuery._unmark( div, "foo" );

	$div.promise( "foo" ).done(function() {
		ok( true, "No more marks" );
		start();
	});
});

test("_mark() and _unmark() default to 'fx'", function() {
	expect(1);

	var div = {},
		$div = jQuery( div );

	stop();

	jQuery._mark( div );
	jQuery._mark( div );
	jQuery._unmark( div, "fx" );
	jQuery._unmark( div );

	$div.promise().done(function() {
		ok( true, "No more marks" );
		start();
	});
});

test("promise()", function() {
	expect(1);

	stop();

	var objects = [];

	jQuery.each( [{}, {}], function( i, div ) {
		var $div = jQuery( div );
		$div.queue(function( next ) {
			setTimeout( function() {
				if ( i ) {
					next();
					setTimeout( function() {
						jQuery._unmark( div );
					}, 20 );
				} else {
					jQuery._unmark( div );
					setTimeout( function() {
						next();
					}, 20 );
				}
			}, 50 );
		}).queue(function( next ) {
			next();
		});
		jQuery._mark( div );
		objects.push( $div );
	});

	jQuery.when.apply( jQuery, objects ).done(function() {
		ok( true, "Deferred resolved" );
		start();
	});

	jQuery.each( objects, function() {
		this.dequeue();
	});
});

test(".promise(obj)", function() {
	expect(2);

	var obj = {};
	var promise = jQuery( "#foo" ).promise( "promise", obj );

	ok( jQuery.isFunction( promise.promise ), ".promise(type, obj) returns a promise" );
	strictEqual( promise, obj, ".promise(type, obj) returns obj" );
});
<commit_msg>Firefox stalls without longer delays.<commit_after>module("queue", { teardown: moduleTeardown });

test("queue() with other types",function() {
	expect(12);
	var counter = 0;

	stop();

	var $div = jQuery({}),
		defer;

	$div.promise("foo").done(function() {
		equal( counter, 0, "Deferred for collection with no queue is automatically resolved" );
	});

	$div
		.queue("foo",function(){
			equal( ++counter, 1, "Dequeuing" );
			jQuery.dequeue(this,"foo");
		})
		.queue("foo",function(){
			equal( ++counter, 2, "Dequeuing" );
			jQuery(this).dequeue("foo");
		})
		.queue("foo",function(){
			equal( ++counter, 3, "Dequeuing" );
		})
		.queue("foo",function(){
			equal( ++counter, 4, "Dequeuing" );
		});

	defer = $div.promise("foo").done(function() {
		equal(  counter, 4, "Testing previous call to dequeue in deferred"  );
		start();
	});

	equal( $div.queue("foo").length, 4, "Testing queue length" );

	equal( $div.queue("foo", undefined).queue("foo").length, 4, ".queue('name',undefined) does nothing but is chainable (#5571)");

	$div.dequeue("foo");

	equal( counter, 3, "Testing previous call to dequeue" );
	equal( $div.queue("foo").length, 1, "Testing queue length" );

	$div.dequeue("foo");

	equal( counter, 4, "Testing previous call to dequeue" );
	equal( $div.queue("foo").length, 0, "Testing queue length" );
});

test("queue(name) passes in the next item in the queue as a parameter", function() {
	expect(2);

	var div = jQuery({});
	var counter = 0;

	div.queue("foo", function(next) {
		equal(++counter, 1, "Dequeueing");
		next();
	}).queue("foo", function(next) {
		equal(++counter, 2, "Next was called");
		next();
	}).queue("bar", function() {
		equal(++counter, 3, "Other queues are not triggered by next()")
	});

	div.dequeue("foo");
});

test("queue() passes in the next item in the queue as a parameter to fx queues", function() {
	expect(3);
	stop();

	var div = jQuery({});
	var counter = 0;

	div.queue(function(next) {
		equal(++counter, 1, "Dequeueing");
		var self = this;
		setTimeout(function() { next() }, 500);
	}).queue(function(next) {
		equal(++counter, 2, "Next was called");
		next();
	}).queue("bar", function() {
		equal(++counter, 3, "Other queues are not triggered by next()")
	});

	jQuery.when( div.promise("fx"), div ).done(function() {
		equal(counter, 2, "Deferreds resolved");
		start();
	});
});

test("callbacks keep their place in the queue", function() {
	expect(5);
	stop();
	var div = jQuery("<div>"),
		counter = 0;

	div.queue(function( next ) {
		equal( ++counter, 1, "Queue/callback order: first called" );
		setTimeout( next, 200 );
	}).show(100, function() {
		equal( ++counter, 2, "Queue/callback order: second called" );
		jQuery(this).hide(100, function() {
			equal( ++counter, 4, "Queue/callback order: fourth called" );
		});
	}).queue(function( next ) {
		equal( ++counter, 3, "Queue/callback order: third called" );
		next();
	});

	div.promise("fx").done(function() {
		equal(counter, 4, "Deferreds resolved");
		jQuery.removeData( div[0], "olddisplay", true );
		start();
	});
});

test("delay()", function() {
	expect(2);
	stop();

	var foo = jQuery({}), run = 0;

	foo.delay(100).queue(function(){
		run = 1;
		ok( true, "The function was dequeued." );
		start();
	});

	equal( run, 0, "The delay delayed the next function from running." );
});

test("delay() can be stopped", function() {
	expect( 3 );
	stop();

	var foo = jQuery({}), run = 0;

	foo
		.queue( "alternate", function( next ) {
			run++;
			ok( true, "This first function was dequeued" );
			next();
		})
		.delay( 1000, "alternate" )
		.queue( "alternate", function() {
			run++;
			ok( true, "The function was dequeued immediately, the delay was stopped" );
		})
		.dequeue( "alternate" )

		// stop( "alternate", false ) will NOT clear the queue, so it should automatically dequeue the next
		.stop( "alternate", false, false )

		// this test
		.delay( 1000 )
		.queue(function() {
			run++;
			ok( false, "This queue should never run" );
		})

		// stop( clearQueue ) should clear the queue
		.stop( true, false );

	equal( run, 2, "Queue ran the proper functions" );

	setTimeout( start, 2000 );
});

test("clearQueue(name) clears the queue", function() {
	expect(2);

	stop()

	var div = jQuery({});
	var counter = 0;

	div.queue("foo", function(next) {
		counter++;
		jQuery(this).clearQueue("foo");
		next();
	}).queue("foo", function(next) {
		counter++;
	});

	div.promise("foo").done(function() {
		ok( true, "dequeue resolves the deferred" );
		start();
	});

	div.dequeue("foo");

	equal(counter, 1, "the queue was cleared");
});

test("clearQueue() clears the fx queue", function() {
	expect(1);

	var div = jQuery({});
	var counter = 0;

	div.queue(function(next) {
		counter++;
		var self = this;
		setTimeout(function() { jQuery(self).clearQueue(); next(); }, 50);
	}).queue(function(next) {
		counter++;
	});

	equal(counter, 1, "the queue was cleared");

	div.removeData();
});

test("_mark() and _unmark()", function() {
	expect(1);

	var div = {},
		$div = jQuery( div );

	stop();

	jQuery._mark( div, "foo" );
	jQuery._mark( div, "foo" );
	jQuery._unmark( div, "foo" );
	jQuery._unmark( div, "foo" );

	$div.promise( "foo" ).done(function() {
		ok( true, "No more marks" );
		start();
	});
});

test("_mark() and _unmark() default to 'fx'", function() {
	expect(1);

	var div = {},
		$div = jQuery( div );

	stop();

	jQuery._mark( div );
	jQuery._mark( div );
	jQuery._unmark( div, "fx" );
	jQuery._unmark( div );

	$div.promise().done(function() {
		ok( true, "No more marks" );
		start();
	});
});

test("promise()", function() {
	expect(1);

	stop();

	var objects = [];

	jQuery.each( [{}, {}], function( i, div ) {
		var $div = jQuery( div );
		$div.queue(function( next ) {
			setTimeout( function() {
				if ( i ) {
					next();
					setTimeout( function() {
						jQuery._unmark( div );
					}, 20 );
				} else {
					jQuery._unmark( div );
					setTimeout( function() {
						next();
					}, 20 );
				}
			}, 50 );
		}).queue(function( next ) {
			next();
		});
		jQuery._mark( div );
		objects.push( $div );
	});

	jQuery.when.apply( jQuery, objects ).done(function() {
		ok( true, "Deferred resolved" );
		start();
	});

	jQuery.each( objects, function() {
		this.dequeue();
	});
});

test(".promise(obj)", function() {
	expect(2);

	var obj = {};
	var promise = jQuery( "#foo" ).promise( "promise", obj );

	ok( jQuery.isFunction( promise.promise ), ".promise(type, obj) returns a promise" );
	strictEqual( promise, obj, ".promise(type, obj) returns obj" );
});
<|endoftext|>


<commit_before>
import AbstractEntity from "idb-entity/es2015/AbstractEntity"
import SubscriptionState from "./SubscriptionState"
import SubscriptionType from "./SubscriptionType"
import objectStore from "../decorator/objectStore"

@objectStore("Subscription")
export default class Subscription extends AbstractEntity {
  /**
   * Internal ID of this subscription record generated by the Indexed DB object
   * store.
   */
  id: number;

  /**
   * The type of this subscription, must be one of the
   * {@linkcode SubscriptionType.*} constants.
   */
  type: string;

  /**
   * The ID of the playlist from which the videos should be retrieved. This
   * is the "uploads" playlist if this is a subscription to a YouTube
   * channel.
   */
  playlistId: string;

  /**
   * The ID of the channel to which the subscription is made to. The field is
   * the ID of the channel owning the playlist for incognito subscriptions to
   * playlist.
   */
  channelId: string;

  /**
   * The state of this subscription, must be one of the
   * {@linkcode SubscriptionState.*} constants.
   */
  state: string;

  /**
   * The last reported error related to this subscription, set to {@code null}
   * if there is no current error.
   */
  lastError: ?string;

  /**
   * The ID of the Google account from which this subscription has been
   * provided. The field is {@code null} if this is an incognito subscription.
   */
  accountId: string;

  /**
   * Set to {@code 1} if this is an incognito subscription (has been provided
   * manually instead of read from YouTube channel subscriptions); set to
   * {@code 0} otherwise.
   */
  isIncognito: number;
}
<commit_msg>fixed a type annotation<commit_after>
import AbstractEntity from "idb-entity/es2015/AbstractEntity"
import SubscriptionState from "./SubscriptionState"
import SubscriptionType from "./SubscriptionType"
import objectStore from "../decorator/objectStore"

@objectStore("Subscription")
export default class Subscription extends AbstractEntity {
  /**
   * Internal ID of this subscription record generated by the Indexed DB object
   * store.
   */
  id: number;

  /**
   * The type of this subscription, must be one of the
   * {@linkcode SubscriptionType.*} constants.
   */
  type: string;

  /**
   * The ID of the playlist from which the videos should be retrieved. This
   * is the "uploads" playlist if this is a subscription to a YouTube
   * channel.
   */
  playlistId: string;

  /**
   * The ID of the channel to which the subscription is made to. The field is
   * the ID of the channel owning the playlist for incognito subscriptions to
   * playlist.
   */
  channelId: string;

  /**
   * The state of this subscription, must be one of the
   * {@linkcode SubscriptionState.*} constants.
   */
  state: string;

  /**
   * The last reported error related to this subscription, set to {@code null}
   * if there is no current error.
   */
  lastError: ?string;

  /**
   * The ID of the Google account from which this subscription has been
   * provided. The field is {@code null} if this is an incognito subscription.
   */
  accountId: ?string;

  /**
   * Set to {@code 1} if this is an incognito subscription (has been provided
   * manually instead of read from YouTube channel subscriptions); set to
   * {@code 0} otherwise.
   */
  isIncognito: number;
}
<|endoftext|>


<commit_before>/*eslint-disable no-console */
"use strict";

module.exports = {
	protectReject(err) {
		if (err && err.stack) {
			console.error(err);
			console.error(err.stack);
		}
		expect(err).toBe(true);
	},

	extendExpect(expect) {
		expect.extend({
			toBeAnyOf(received, expected) {
				let pass = false;
				for (const item of expected) {
					if (received === item) {
						pass = true;
						break;
					}
				}

				let list = expected
					.map(item => item.toString())
					.join(", ");
				let message = `Expected ${received.toString()} to be any of [${list}]`;

				return {
					actual: received,
					message,
					pass
				};
			},
		});
	}
};
<commit_msg>fix "toBeAnyOf" extender<commit_after>/*eslint-disable no-console */
"use strict";

module.exports = {
	protectReject(err) {
		if (err && err.stack) {
			console.error(err);
			console.error(err.stack);
		}
		expect(err).toBe(true);
	},

	extendExpect(expect) {
		expect.extend({
			toBeAnyOf(received, expected) {
				let pass = false;
				for (const item of expected) {
					if (received === item) {
						pass = true;
						break;
					}
				}

				let list = expected
					.map(item => item.toString())
					.join(", ");
				let message = `Expected ${received.toString()} to be any of [${list}]`;

				return {
					actual: received,
					message: () => message,
					pass
				};
			},
		});
	}
};
<|endoftext|>


<commit_before>// Positons of aliens in each level
  var levelData = {
     1:  [[0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,3,3,3,3,0,0,0],
          [0,0,0,0,2,2,2,2,0,0,0],
          [0,0,0,0,1,1,1,1,0,0,0]],
      2:  [[0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,3,3,3,3,3,3,0,0],
          [0,0,0,3,3,3,3,3,3,0,0],
          [0,0,0,2,2,2,2,2,2,0,0],
          [0,0,0,2,2,2,2,2,2,0,0],
          [0,0,0,1,1,1,1,1,1,0,0],
          [0,0,0,1,1,1,1,1,1,0,0]] };

// Positions of graphics on the sprite card

  var spriteData = {
    'alien1': { sx: 0,  sy: 0,  w: 23, h: 23, cls: Alien },
    'alien2': { sx: 24,  sy: 0, w: 23, h: 23, cls: Alien },
    'alien3': { sx: 48,  sy: 0, w: 23, h: 23, cls: Alien },
    'player': { sx: 0,  sy: 24, w: 22, h: 22, cls: Player },
    'missile': { sx: 2,  sy: 48, w: 5,  h: 5, cls: Missile }
  }

// Start game callback screen - what appears on the start screen - links to engine .js
  function startGame() {
    var screen = new GameScreen("Clown Invaders","Please press space to begin",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
    Game.loop();
  }

// End game callback screen - same as above but when the user dies
  function endGame() {
    var screen = new GameScreen("Game Over","Dare to try again? Press space!",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
  }

// Win screen - what appears when the user wins
  function winGame() {
    var screen = new GameScreen("You Win!","Want another go? Press space!",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
  }

// Attaches audio to functions
  $(function() {
    GameAudio.load({ 'fire' : 'media/laser.ogg', 'die' : 'media/explosion.ogg' },
                   function() {

// Initializes code through all documents
Game.initialize("#gameboard", levelData, spriteData,
                                      { "start": startGame,
                                        "die"  : endGame,
                                        "win"  : winGame });
                   });
   });

<commit_msg>New level added to game<commit_after>// Positons of aliens in each level
  var levelData = {
     1:  [[0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,3,3,3,3,0,0,0],
          [0,0,0,0,2,2,2,2,0,0,0],
          [0,0,0,0,1,1,1,1,0,0,0]],
      2:  [[0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,3,3,3,3,3,3,0,0],
          [0,0,0,3,3,3,3,3,3,0,0],
          [0,0,0,2,2,2,2,2,2,0,0],
          [0,0,0,2,2,2,2,2,2,0,0],
          [0,0,0,1,1,1,1,1,1,0,0],
          [0,0,0,1,1,1,1,1,1,0,0]],
      3:  [[0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,0,0,0,0,0,0,0,0,0,0],
          [0,3,3,3,3,3,3,3,3,3,0],
          [0,3,3,3,3,3,3,3,3,3,0],
          [0,2,2,2,2,2,2,2,2,2,0],
          [0,2,2,2,2,2,2,2,2,2,0],
          [0,1,1,1,1,1,1,1,1,1,0],
          [0,1,1,1,1,1,1,1,1,1,0]] };

// Positions of graphics on the sprite card

  var spriteData = {
    'alien1': { sx: 0,  sy: 0,  w: 23, h: 23, cls: Alien },
    'alien2': { sx: 24,  sy: 0, w: 23, h: 23, cls: Alien },
    'alien3': { sx: 48,  sy: 0, w: 23, h: 23, cls: Alien },
    'player': { sx: 0,  sy: 24, w: 22, h: 22, cls: Player },
    'missile': { sx: 2,  sy: 48, w: 5,  h: 5, cls: Missile }
  }

// Start game callback screen - what appears on the start screen - links to engine .js
  function startGame() {
    var screen = new GameScreen("Clown Invaders","Please press space to begin",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
    Game.loop();
  }

// End game callback screen - same as above but when the user dies
  function endGame() {
    var screen = new GameScreen("Game Over","Dare to try again? Press space!",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
  }

// Win screen - what appears when the user wins
  function winGame() {
    var screen = new GameScreen("You Win!","Want another go? Press space!",
                                 function() {
                                     Game.loadBoard(new GameBoard(1));
                                 });
    Game.loadBoard(screen);
  }

// Attaches audio to functions
  $(function() {
    GameAudio.load({ 'fire' : 'media/laser.ogg', 'die' : 'media/explosion.ogg' },
                   function() {

// Initializes code through all documents
Game.initialize("#gameboard", levelData, spriteData,
                                      { "start": startGame,
                                        "die"  : endGame,
                                        "win"  : winGame });
                   });
   });

<|endoftext|>


<commit_before>/*

Jappix - An open social platform
These are the links JS script for Jappix

-------------------------------------------------

License: AGPL
Authors: Valérian Saliou, Maranda
Last revision: 24/06/11

*/

// Apply links in a string
function applyLinks(string, mode, style) {
	// Special stuffs
	var style, target;

	// Links style
	if(!style)
		style = '';
	else
		style = ' style="' + style + '"';

	// Open in new tabs
	if(mode != 'xhtml-im')
		target = ' target="_blank"';
	else
		target = '';

	// XMPP address
	string = string.replace(/(\s|
|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(\s|$)/gi, '$1$2$5');

	// Simple link
	string = string.replace(/(\s|
|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1$2');

	return string;
}
<commit_msg>Links fix.<commit_after>/*

Jappix - An open social platform
These are the links JS script for Jappix

-------------------------------------------------

License: AGPL
Authors: Valérian Saliou, Maranda
Last revision: 26/08/11

*/

// Apply links in a string
function applyLinks(string, mode, style) {
	// Special stuffs
	var style, target;

	// Links style
	if(!style)
		style = '';
	else
		style = ' style="' + style + '"';

	// Open in new tabs
	if(mode != 'xhtml-im')
		target = ' target="_blank"';
	else
		target = '';

	// XMPP address
	string = string.replace(/(\s|
|^)(([a-zA-Z0-9\._-]+)@([a-zA-Z0-9\.\/_-]+))(,|\s|$)/gi, '$1$2$5');

	// Simple link
	string = string.replace(/(\s|
|^|\()((https?|ftp|file|xmpp|irc|mailto|vnc|webcal|ssh|ldap|smb|magnet|spotify)(:)([^<>'"\s\)]+))/gim, '$1$2');

	return string;
}
<|endoftext|>


<commit_before>$( document ).ready(function() {
    if (!window.location.origin) {
        window.location.origin = window.location.protocol+"//"+window.location.host;
    }
    // If already logged in, go to home page
    if (localStorage.getItem('github_oauth_token')) {
        window.location.replace(target_url);
    }
    // Check for redirect_uri
    var target_url = sessionStorage.getItem('login_redirect');
    if (!target_url) {
        target_url = window.location.origin;
    } else {
        sessionStorage.removeItem('login_redirect');
    }
    // Get temporary code from HTTP GET
    var match = window.location.href.match(/\?code=(.*)/)[1];
    // If found, pass the temp token to gatekeeper
    if (match) {
        var code = match[1];
        $.getJSON('http://auth.design.ros2.org/authenticate/' + code, function(data) {
            // Once gatekeeper gets back, check for the token
            if (!data.token) {
                // If the token is not set, then display an error
                $( 'div.content-container div' ).replaceWith([
                    '
',
                    '
',
                    '
Error
',
                    '
',
                    '
',
                    '    Error logging in using Github: ' + data.error,
                    '
',
                    '
'].join('\n'));
            } else {
                // Else store the key in the the localStorage
                localStorage.setItem('github_oauth_token', data.token);
                window.location.replace(target_url);
            }
        });
    } else {
        // If no match return the main page
        window.location.replace(window.location.origin);
    }
});
<commit_msg>fix regression for login<commit_after>$( document ).ready(function() {
    if (!window.location.origin) {
        window.location.origin = window.location.protocol+"//"+window.location.host;
    }
    // If already logged in, go to home page
    if (localStorage.getItem('github_oauth_token')) {
        window.location.replace(target_url);
    }
    // Check for redirect_uri
    var target_url = sessionStorage.getItem('login_redirect');
    if (!target_url) {
        target_url = window.location.origin;
    } else {
        sessionStorage.removeItem('login_redirect');
    }
    // Get temporary code from HTTP GET
    var match = window.location.href.match(/\?code=(.*)/);
    // If found, pass the temp token to gatekeeper
    if (match) {
        var code = match[1];
        $.getJSON('http://auth.design.ros2.org/authenticate/' + code, function(data) {
            // Once gatekeeper gets back, check for the token
            if (!data.token) {
                // If the token is not set, then display an error
                $( 'div.content-container div' ).replaceWith([
                    '
',
                    '
',
                    '
Error
',
                    '
',
                    '
',
                    '    Error logging in using Github: ' + data.error,
                    '
',
                    '
'].join('\n'));
            } else {
                // Else store the key in the the localStorage
                localStorage.setItem('github_oauth_token', data.token);
                window.location.replace(target_url);
            }
        });
    } else {
        // If no match return the main page
        window.location.replace(window.location.origin);
    }
});
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { connect } from 'react-redux';
import { navigateToCurrentRoute, navigateToChallenge, navigateToHome } from '../actions';
import ChallengeContainer from './challenge-container';
import FVChallengeContainer from './fv-challenge-container';
import AuthoringUtils from '../utilities/authoring-utils';

function hasChangedRouteParams(currentRouteSpec, routeParams) {
  if (!currentRouteSpec) {
    return true;
  }
  const { level: currLevel, mission: currMission, challenge: currChallenge } = currentRouteSpec,
        currLevelStr = String(currLevel + 1),
        currMissionStr = String(currMission + 1),
        currChallengeStr = String(currChallenge + 1);
  return (isValidRouteParams(routeParams) &&
        ((routeParams.mission !== currMissionStr) || (routeParams.challenge !== currChallengeStr) || (routeParams.level !== currLevelStr)));
}

function isValidRouteParams(routeParams) {
  return routeParams.mission && routeParams.challenge && routeParams.level;
}

function mapContainerNameToContainer(containerName) {
  switch (containerName) {
    case 'FVContainer':
      return FVChallengeContainer;
    default:
      return ChallengeContainer;
  }
}

class ChallengeContainerSelector extends Component {

  static propTypes = {
    authoring: PropTypes.object.isRequired,
    currentRouteSpec: PropTypes.shape({
      level: PropTypes.number,
      mission: PropTypes.number,
      challenge: PropTypes.number
    }),
    currentRoom: PropTypes.string,
    // Potentially updated, incoming route parameters
    routeParams: PropTypes.shape({
      level: PropTypes.string,
      mission: PropTypes.string,
      challenge: PropTypes.string,
      challengeId: PropTypes.string
    }),
    navigateToChallenge: PropTypes.func,
    navigateToCurrentRoute: PropTypes.func
  }

  componentWillMount() {
    const { navigateToCurrentRoute, navigateToChallenge, navigateToHome, authoring } = this.props;
    // the URL's challengeId is only used for initial routing, so prioritize the numeric route params
    let routeParams = this.props.routeParams;
    if (routeParams.challengeId) {
      if (routeParams.challengeId === "home") {
        if (this.props.currentRoom !== "home") {
          navigateToHome();
        }
        return;
      }
      routeParams = AuthoringUtils.challengeIdToRouteParams(authoring, routeParams.challengeId);
    }
    if (isValidRouteParams(routeParams)) {
      if (hasChangedRouteParams(this.props.currentRouteSpec, routeParams)) {
        navigateToCurrentRoute({level: routeParams.level-1, mission: routeParams.mission-1, challenge: routeParams.challenge-1});
      }
    } else {
      navigateToChallenge({level: 0, mission: 0, challenge: 0});
    }
  }

  componentWillReceiveProps(newProps) {
    const { currentRouteSpec, navigateToCurrentRoute, navigateToHome, authoring } = newProps;
    let { routeParams } = newProps;
    if (routeParams.challengeId) {
      if (routeParams.challengeId === "home") {
        if (newProps.currentRoom !== "home") {
          navigateToHome();
        }
        return;
      }
      routeParams = AuthoringUtils.challengeIdToRouteParams(authoring, routeParams.challengeId);
    }
    if (hasChangedRouteParams(currentRouteSpec, routeParams)) {
      navigateToCurrentRoute({level: routeParams.level-1, mission: routeParams.mission-1, challenge: routeParams.challenge-1});
    }
  }

  render() {
    const { authoring, currentRouteSpec, ...otherProps } = this.props;
    let ContainerClass;
    if (currentRouteSpec) {
      const authoredChallenge = AuthoringUtils.getChallengeDefinition(authoring, currentRouteSpec),
            containerName = authoredChallenge.container;
      ContainerClass = mapContainerNameToContainer(containerName);
    } else {
      ContainerClass = FVChallengeContainer;
    }
    return (
      <ContainerClass {...otherProps} />
    );
  }
}

function mapStateToProps (state) {
  return {
    authoring: state.authoring,
    currentRouteSpec: state.routeSpec,
    currentRoom: state.location && state.location.id
  };
}

function mapDispatchToProps(dispatch) {
  return {
    navigateToChallenge: (routeSpec) => dispatch(navigateToChallenge(routeSpec)),
    navigateToCurrentRoute: (routeSpec) => dispatch(navigateToCurrentRoute(routeSpec)),
    navigateToHome: () => dispatch(navigateToHome())
  };
}

const DragDropChallengeContainerSelector = DragDropContext(HTML5Backend)(ChallengeContainerSelector),
      ConnectedChallengeContainerSelector = connect(mapStateToProps, mapDispatchToProps)(DragDropChallengeContainerSelector);
export default ConnectedChallengeContainerSelector;
<commit_msg>Navigate to home by default if no url route params<commit_after>import React, { Component, PropTypes } from 'react';
import { DragDropContext } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import { connect } from 'react-redux';
import { navigateToCurrentRoute, navigateToChallenge, navigateToHome } from '../actions';
import ChallengeContainer from './challenge-container';
import FVChallengeContainer from './fv-challenge-container';
import AuthoringUtils from '../utilities/authoring-utils';

function hasChangedRouteParams(currentRouteSpec, routeParams) {
  if (!currentRouteSpec) {
    return true;
  }
  const { level: currLevel, mission: currMission, challenge: currChallenge } = currentRouteSpec,
        currLevelStr = String(currLevel + 1),
        currMissionStr = String(currMission + 1),
        currChallengeStr = String(currChallenge + 1);
  return (isValidRouteParams(routeParams) &&
        ((routeParams.mission !== currMissionStr) || (routeParams.challenge !== currChallengeStr) || (routeParams.level !== currLevelStr)));
}

function isValidRouteParams(routeParams) {
  return routeParams.mission && routeParams.challenge && routeParams.level;
}

function mapContainerNameToContainer(containerName) {
  switch (containerName) {
    case 'FVContainer':
      return FVChallengeContainer;
    default:
      return ChallengeContainer;
  }
}

class ChallengeContainerSelector extends Component {

  static propTypes = {
    authoring: PropTypes.object.isRequired,
    currentRouteSpec: PropTypes.shape({
      level: PropTypes.number,
      mission: PropTypes.number,
      challenge: PropTypes.number
    }),
    currentRoom: PropTypes.string,
    // Potentially updated, incoming route parameters
    routeParams: PropTypes.shape({
      level: PropTypes.string,
      mission: PropTypes.string,
      challenge: PropTypes.string,
      challengeId: PropTypes.string
    }),
    navigateToChallenge: PropTypes.func,
    navigateToCurrentRoute: PropTypes.func
  }

  componentWillMount() {
    const { navigateToCurrentRoute, navigateToChallenge, navigateToHome, authoring } = this.props;
    // the URL's challengeId is only used for initial routing, so prioritize the numeric route params
    let routeParams = this.props.routeParams;
    if (routeParams.challengeId) {
      if (routeParams.challengeId === "home") {
        if (this.props.currentRoom !== "home") {
          navigateToHome();
        }
        return;
      }
      routeParams = AuthoringUtils.challengeIdToRouteParams(authoring, routeParams.challengeId);
    }
    if (isValidRouteParams(routeParams)) {
      if (hasChangedRouteParams(this.props.currentRouteSpec, routeParams)) {
        navigateToCurrentRoute({level: routeParams.level-1, mission: routeParams.mission-1, challenge: routeParams.challenge-1});
      }
    } else {
      navigateToHome();
    }
  }

  componentWillReceiveProps(newProps) {
    const { currentRouteSpec, navigateToCurrentRoute, navigateToHome, authoring } = newProps;
    let { routeParams } = newProps;
    if (routeParams.challengeId) {
      if (routeParams.challengeId === "home") {
        if (newProps.currentRoom !== "home") {
          navigateToHome();
        }
        return;
      }
      routeParams = AuthoringUtils.challengeIdToRouteParams(authoring, routeParams.challengeId);
    }
    if (hasChangedRouteParams(currentRouteSpec, routeParams)) {
      navigateToCurrentRoute({level: routeParams.level-1, mission: routeParams.mission-1, challenge: routeParams.challenge-1});
    }
  }

  render() {
    const { authoring, currentRouteSpec, ...otherProps } = this.props;
    let ContainerClass;
    if (currentRouteSpec) {
      const authoredChallenge = AuthoringUtils.getChallengeDefinition(authoring, currentRouteSpec),
            containerName = authoredChallenge.container;
      ContainerClass = mapContainerNameToContainer(containerName);
    } else {
      ContainerClass = FVChallengeContainer;
    }
    return (
      <ContainerClass {...otherProps} />
    );
  }
}

function mapStateToProps (state) {
  return {
    authoring: state.authoring,
    currentRouteSpec: state.routeSpec,
    currentRoom: state.location && state.location.id
  };
}

function mapDispatchToProps(dispatch) {
  return {
    navigateToChallenge: (routeSpec) => dispatch(navigateToChallenge(routeSpec)),
    navigateToCurrentRoute: (routeSpec) => dispatch(navigateToCurrentRoute(routeSpec)),
    navigateToHome: () => dispatch(navigateToHome())
  };
}

const DragDropChallengeContainerSelector = DragDropContext(HTML5Backend)(ChallengeContainerSelector),
      ConnectedChallengeContainerSelector = connect(mapStateToProps, mapDispatchToProps)(DragDropChallengeContainerSelector);
export default ConnectedChallengeContainerSelector;
<|endoftext|>


<commit_before>"use strict";

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');

//  ---------------------------------------------------------------------------

module.exports = class lykke extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lykke',
            'name': 'Lykke',
            'countries': 'CH',
            'version': 'v1',
            'rateLimit': 200,
            'has': {
                'CORS': false,
                'fetchOHLCV': false,
                'fetchTrades': false,
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/34487620-3139a7b0-efe6-11e7-90f5-e520cef74451.jpg',
                'api': {
                    'mobile': 'https://api.lykkex.com/api',
                    'public': 'https://hft-api.lykke.com/api',
                    'private': 'https://hft-api.lykke.com/api',
                    'test': {
                        'mobile': 'https://api.lykkex.com/api',
                        'public': 'https://hft-service-dev.lykkex.net/api',
                        'private': 'https://hft-service-dev.lykkex.net/api',
                    },
                },
                'www': 'https://www.lykke.com',
                'doc': [
                    'https://hft-api.lykke.com/swagger/ui/',
                    'https://www.lykke.com/lykke_api',
                ],
                'fees': 'https://www.lykke.com/trading-conditions',
            },
            'api': {
                'mobile': {
                    'get': [
                        'AllAssetPairRates/{market}',
                    ],
                },
                'public': {
                    'get': [
                        'AssetPairs',
                        'AssetPairs/{id}',
                        'IsAlive',
                        'OrderBooks',
                        'OrderBooks/{AssetPairId}',
                    ],
                },
                'private': {
                    'get': [
                        'Orders',
                        'Orders/{id}',
                        'Wallets',
                    ],
                    'post': [
                        'Orders/limit',
                        'Orders/market',
                        'Orders/{id}/Cancel',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0010,
                    'taker': 0.0019,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0.001,
                    },
                    'deposit': {
                        'BTC': 0,
                    },
                },
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets ();
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = balance['AssetId'];
            let total = balance['Balance'];
            let used = balance['Reserved'];
            let free = total - used;
            result[currency] = {
                'free': free,
                'used': used,
                'total': total,
            };
        }
        return this.parseBalance (result);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostOrdersIdCancel ({ 'id': id });
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let query = {
            'AssetPairId': market['id'],
            'OrderAction': this.capitalize (side),
            'Volume': amount,
        };
        if (type == 'market') {
            query['Asset'] = (side == 'buy') ? market['base'] : market['quote'];
        } else if (type == 'limit') {
            query['Price'] = price;
        }
        let method = 'privatePostOrders' + this.capitalize (type);
        let result = await this[method] (this.extend (query, params));
        return {
            'id': undefined,
            'info': result,
        };
    }

    async fetchMarkets () {
        let markets = await this.publicGetAssetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['Id'];
            let base = market['BaseAssetId'];
            let quote = market['QuotingAssetId'];
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = market['Name'];
            let precision = {
                'amount': market['Accuracy'],
                'price': market['InvertedAccuracy'],
            };
            result.push (this.extend (this.fees['trading'], {
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'info': market,
                'lot': Math.pow (10, -precision['amount']),
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': Math.pow (10, -precision['amount']),
                        'max': Math.pow (10, precision['amount']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                },
            }));
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        ticker = ticker['Result'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['Rate']['Bid']),
            'ask': parseFloat (ticker['Rate']['Ask']),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.mobileGetAllAssetPairRatesMarket (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseOrderStatus (status) {
        if (status == 'Pending') {
            return 'open';
        } else if (status == 'InOrderBook') {
            return 'open';
        } else if (status == 'Processing') {
            return 'open';
        } else if (status == 'Matched') {
            return 'closed';
        } else if (status == 'Cancelled') {
            return 'canceled';
        } else if (status == 'NotEnoughFunds') {
            return 'NotEnoughFunds';
        } else if (status == 'NoLiquidity') {
            return 'NoLiquidity';
        } else if (status == 'UnknownAsset') {
            return 'UnknownAsset';
        } else if (status == 'LeadToNegativeSpread') {
            return 'LeadToNegativeSpread';
        }
        return status;
    }

    parseOrder (order, market = undefined) {
        let status = this.parseOrderStatus (order['Status']);
        let symbol = undefined;
        if (!market) {
            if ('AssetPairId' in order)
                if (order['AssetPairId'] in this.markets_by_id)
                    market = this.markets_by_id[order['AssetPairId']];
        }
        if (market)
            symbol = market['symbol'];
        let timestamp = undefined;
        if ('LastMatchTime' in order) {
            timestamp = this.parse8601 (order['LastMatchTime']);
        } else if ('Registered' in order) {
            timestamp = this.parse8601 (order['Registered']);
        } else if ('CreatedAt' in order) {
            timestamp = this.parse8601 (order['CreatedAt']);
        }
        let price = this.safeFloat (order, 'Price');
        let amount = this.safeFloat (order, 'Volume');
        let remaining = this.safeFloat (order, 'RemainingVolume');
        let filled = amount - remaining;
        let cost = filled * price;
        let result = {
            'info': order,
            'id': order['Id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': price,
            'cost': cost,
            'average': undefined,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders ();
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'InOrderBook',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'Matched',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOrderBook (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.publicGetOrderBooksAssetPairId (this.extend ({
            'AssetPairId': this.marketId (symbol),
        }, params));
        let orderbook = {
            'timestamp': undefined,
            'bids': [],
            'asks': [],
        };
        let timestamp = undefined;
        for (let i = 0; i < response.length; i++) {
            let side = response[i];
            if (side['IsBuy']) {
                orderbook['bids'] = this.arrayConcat (orderbook['bids'], side['Prices']);
            } else {
                orderbook['asks'] = this.arrayConcat (orderbook['asks'], side['Prices']);
            }
            let timestamp = this.parse8601 (side['Timestamp']);
            if (!orderbook['timestamp']) {
                orderbook['timestamp'] = timestamp;
            } else {
                orderbook['timestamp'] = Math.max (orderbook['timestamp'], timestamp);
            }
        }
        if (!timestamp)
            timestamp = this.milliseconds ();
        return this.parseOrderBook (orderbook, orderbook['timestamp'], 'bids', 'asks', 'Price', 'Volume');
    }

    parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
        let price = parseFloat (bidask[priceKey]);
        let amount = parseFloat (bidask[amountKey]);
        if (amount < 0)
            amount = -amount;
        return [ price, amount ];
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api == 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else if (api == 'private') {
            if (method == 'GET')
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            this.checkRequiredCredentials ();
            headers = {
                'api-key': this.apiKey,
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            };
            if (method == 'POST')
                if (Object.keys (params).length)
                    body = this.json (params);
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
}
<commit_msg>lykke: linting<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');

//  ---------------------------------------------------------------------------

module.exports = class lykke extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'lykke',
            'name': 'Lykke',
            'countries': 'CH',
            'version': 'v1',
            'rateLimit': 200,
            'has': {
                'CORS': false,
                'fetchOHLCV': false,
                'fetchTrades': false,
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': false,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/34487620-3139a7b0-efe6-11e7-90f5-e520cef74451.jpg',
                'api': {
                    'mobile': 'https://api.lykkex.com/api',
                    'public': 'https://hft-api.lykke.com/api',
                    'private': 'https://hft-api.lykke.com/api',
                    'test': {
                        'mobile': 'https://api.lykkex.com/api',
                        'public': 'https://hft-service-dev.lykkex.net/api',
                        'private': 'https://hft-service-dev.lykkex.net/api',
                    },
                },
                'www': 'https://www.lykke.com',
                'doc': [
                    'https://hft-api.lykke.com/swagger/ui/',
                    'https://www.lykke.com/lykke_api',
                ],
                'fees': 'https://www.lykke.com/trading-conditions',
            },
            'api': {
                'mobile': {
                    'get': [
                        'AllAssetPairRates/{market}',
                    ],
                },
                'public': {
                    'get': [
                        'AssetPairs',
                        'AssetPairs/{id}',
                        'IsAlive',
                        'OrderBooks',
                        'OrderBooks/{AssetPairId}',
                    ],
                },
                'private': {
                    'get': [
                        'Orders',
                        'Orders/{id}',
                        'Wallets',
                    ],
                    'post': [
                        'Orders/limit',
                        'Orders/market',
                        'Orders/{id}/Cancel',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.0010,
                    'taker': 0.0019,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {
                        'BTC': 0.001,
                    },
                    'deposit': {
                        'BTC': 0,
                    },
                },
            },
        });
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetWallets ();
        let result = { 'info': balances };
        for (let i = 0; i < balances.length; i++) {
            let balance = balances[i];
            let currency = balance['AssetId'];
            let total = balance['Balance'];
            let used = balance['Reserved'];
            let free = total - used;
            result[currency] = {
                'free': free,
                'used': used,
                'total': total,
            };
        }
        return this.parseBalance (result);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        return await this.privatePostOrdersIdCancel ({ 'id': id });
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let query = {
            'AssetPairId': market['id'],
            'OrderAction': this.capitalize (side),
            'Volume': amount,
        };
        if (type === 'market') {
            query['Asset'] = (side === 'buy') ? market['base'] : market['quote'];
        } else if (type === 'limit') {
            query['Price'] = price;
        }
        let method = 'privatePostOrders' + this.capitalize (type);
        let result = await this[method] (this.extend (query, params));
        return {
            'id': undefined,
            'info': result,
        };
    }

    async fetchMarkets () {
        let markets = await this.publicGetAssetPairs ();
        let result = [];
        for (let i = 0; i < markets.length; i++) {
            let market = markets[i];
            let id = market['Id'];
            let base = market['BaseAssetId'];
            let quote = market['QuotingAssetId'];
            base = this.commonCurrencyCode (base);
            quote = this.commonCurrencyCode (quote);
            let symbol = market['Name'];
            let precision = {
                'amount': market['Accuracy'],
                'price': market['InvertedAccuracy'],
            };
            result.push (this.extend (this.fees['trading'], {
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'active': true,
                'info': market,
                'lot': Math.pow (10, -precision['amount']),
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': Math.pow (10, -precision['amount']),
                        'max': Math.pow (10, precision['amount']),
                    },
                    'price': {
                        'min': Math.pow (10, -precision['price']),
                        'max': Math.pow (10, precision['price']),
                    },
                },
            }));
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        ticker = ticker['Result'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['Rate']['Bid']),
            'ask': parseFloat (ticker['Rate']['Ask']),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': undefined,
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.mobileGetAllAssetPairRatesMarket (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseOrderStatus (status) {
        if (status === 'Pending') {
            return 'open';
        } else if (status === 'InOrderBook') {
            return 'open';
        } else if (status === 'Processing') {
            return 'open';
        } else if (status === 'Matched') {
            return 'closed';
        } else if (status === 'Cancelled') {
            return 'canceled';
        } else if (status === 'NotEnoughFunds') {
            return 'NotEnoughFunds';
        } else if (status === 'NoLiquidity') {
            return 'NoLiquidity';
        } else if (status === 'UnknownAsset') {
            return 'UnknownAsset';
        } else if (status === 'LeadToNegativeSpread') {
            return 'LeadToNegativeSpread';
        }
        return status;
    }

    parseOrder (order, market = undefined) {
        let status = this.parseOrderStatus (order['Status']);
        let symbol = undefined;
        if (!market) {
            if ('AssetPairId' in order)
                if (order['AssetPairId'] in this.markets_by_id)
                    market = this.markets_by_id[order['AssetPairId']];
        }
        if (market)
            symbol = market['symbol'];
        let timestamp = undefined;
        if ('LastMatchTime' in order) {
            timestamp = this.parse8601 (order['LastMatchTime']);
        } else if ('Registered' in order) {
            timestamp = this.parse8601 (order['Registered']);
        } else if ('CreatedAt' in order) {
            timestamp = this.parse8601 (order['CreatedAt']);
        }
        let price = this.safeFloat (order, 'Price');
        let amount = this.safeFloat (order, 'Volume');
        let remaining = this.safeFloat (order, 'RemainingVolume');
        let filled = amount - remaining;
        let cost = filled * price;
        let result = {
            'info': order,
            'id': order['Id'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'type': undefined,
            'side': undefined,
            'price': price,
            'cost': cost,
            'average': undefined,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': undefined,
        };
        return result;
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        let response = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (response);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders ();
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'InOrderBook',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        let response = await this.privateGetOrders (this.extend ({
            'status': 'Matched',
        }, params));
        return this.parseOrders (response, undefined, since, limit);
    }

    async fetchOrderBook (symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let response = await this.publicGetOrderBooksAssetPairId (this.extend ({
            'AssetPairId': this.marketId (symbol),
        }, params));
        let orderbook = {
            'timestamp': undefined,
            'bids': [],
            'asks': [],
        };
        let timestamp = undefined;
        for (let i = 0; i < response.length; i++) {
            let side = response[i];
            if (side['IsBuy']) {
                orderbook['bids'] = this.arrayConcat (orderbook['bids'], side['Prices']);
            } else {
                orderbook['asks'] = this.arrayConcat (orderbook['asks'], side['Prices']);
            }
            let timestamp = this.parse8601 (side['Timestamp']);
            if (!orderbook['timestamp']) {
                orderbook['timestamp'] = timestamp;
            } else {
                orderbook['timestamp'] = Math.max (orderbook['timestamp'], timestamp);
            }
        }
        if (!timestamp)
            timestamp = this.milliseconds ();
        return this.parseOrderBook (orderbook, orderbook['timestamp'], 'bids', 'asks', 'Price', 'Volume');
    }

    parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
        let price = parseFloat (bidask[priceKey]);
        let amount = parseFloat (bidask[amountKey]);
        if (amount < 0)
            amount = -amount;
        return [ price, amount ];
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else if (api === 'private') {
            if (method === 'GET')
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            this.checkRequiredCredentials ();
            headers = {
                'api-key': this.apiKey,
                'Accept': 'application/json',
                'Content-Type': 'application/json',
            };
            if (method === 'POST')
                if (Object.keys (params).length)
                    body = this.json (params);
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>var should = require('should');
var video = require('../../lib/video');

describe('Video', function() {
    'use strict';

    describe('https://www.youtube.com/watch?v=dQw4w9WgXcQ', function() {

        it('for a url www.youtube.com is a youtube video', function(done) {
            var url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('http://www.youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('http://youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('https://youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

    });
});
<commit_msg>Adding tests for parsing youtube video URLs<commit_after>var should = require('should');
var video = require('../../lib/video');

describe('Video', function() {
    'use strict';

    describe('when i receive a youtube video url', function() {

        it('for a url www.youtube.com is a youtube video', function(done) {
            var url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('http://www.youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "http://www.youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('http://youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "http://youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('https://youtube.com/watch?v=dQw4w9WgXcQ', function(done) {
            var url = "https://youtube.com/watch?v=dQw4w9WgXcQ";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

        it('https://youtu.be/6DzSAaNQHR8', function(done) {
            var url = "https://youtu.be/6DzSAaNQHR8";
            var res = video.getCodeAndTypeFromRequest(url);
            should.equal(res[0], "dQw4w9WgXcQ");
            should.equal(res[1], "youtube");
            done();
        });

    });
});
<|endoftext|>