<commit_before>// 
//  fifteens.js
//  
//  Created by <NAME> on 2011-04-10.
//  Copyright 2011 ok<EMAIL>.ru. All rights reserved.
// 

$(function(){
  
  /*
    Tile model and view
  */
  window.Tile = Backbone.Model.extend({
    
    initialize: function(){
      if (!this.get('empty')) {
        this.set({ empty: false });
      }  
    },
    
    isEmpty: function(){
      return this.get('empty');
    },
    
    play: function(){
      var board = this.collection;
      var tilePos = this.get('position');
      var emptyPos = board.getEmptyTile().get('position');
      
      board.getEmptyTile().set({ position: tilePos }, { silent: true });
      this.set({ position: emptyPos });
      game.set({ moves: game.get('moves') + 1 });
    },
    
    canBePlayed: function(){
      var boardSize = this.collection.SIZE;
      var tilePos = this.get('position');
      var emptyPos = this.collection.getEmptyTile().get('position');
      var delta = Math.abs(tilePos - emptyPos);
      
      if(delta == 1 || delta == boardSize) {
        // Empty is in first row. Previous tile can not be played
        if(emptyPos % boardSize == 0 && tilePos == (emptyPos - 1))
          return false;
        // Empty is in last row. Next tile can not be played
        else if((emptyPos + 1) % boardSize == 0 && tilePos == (emptyPos + 1))
          return false;
        else
          // If true, return useful data so we can use it in views
          return {
            real: (tilePos - emptyPos),
            delta: delta
          };
      } else {
        return false;
      }
    },

  });
  window.TileView = Backbone.View.extend({
    
    WIDTH: 144,
    HEIGHT: 136,
    
    tagName: 'li',
    
    className: 'b-tile',
    
    template: _.template("<p><%= label %></p>"),
    
    events: {
      'tap'        : 'playTile',
      'touchstart' : 'dragTileStart',
      'touchmove'  : 'dragTileMove',
      'touchend'   : 'dragTileEnd'
    },
    
    initialize: function() {
      _.bindAll(this, 'render', 'playTile', 'dragTileStart', 'dragTileMove', 'dragTileEnd');
      this.model.bind('change', this.render);
      this.model.view = this;
    },

    render: function() {
      tileData = this.model.toJSON();
      $(this.el).html(this.template(tileData));
      
      if(tileData.empty) $(this.el).addClass('b-tile_empty');
      
      var board = this.model.collection;
      
      var left = (tileData.position % board.SIZE) * this.WIDTH;
      var top = (Math.ceil((tileData.position + 1) / board.SIZE) - 1) * this.HEIGHT;
      
      var el = $(this.el);
      
      el.css({ 'z-index': tileData.position }).anim({ translate: left + 'px, ' + top + 'px'}, 0.125, 'ease-out');
      
      return this;
    },
    
    playTile: function(){
      if(this.model.canBePlayed()) this.model.play();
    },
    
    dragTileStart: function(e){
      this.touch = {};
      this.touch.x1 = e.touches[0].pageX;
      this.touch.y1 = e.touches[0].pageY;
      
      var canBePlayed = this.model.canBePlayed();
      
      if(canBePlayed) {
        this.playing = true;
        this.horizontal = (canBePlayed.delta == 1) ? true : false;
        
        this.moveTo = (this.horizontal && canBePlayed.real < 0) ? 'right' : 
                      (this.horizontal && canBePlayed.real > 0)  ? 'left' : 
                      (!this.horizontal && canBePlayed.real < 0) ? 'bottom' : 
                      (!this.horizontal && canBePlayed.real > 0) ? 'top' : false;
        
        this.originalTransform = _.map($(this.el).css('-webkit-transform').replace('translate(','').split(','), function(component){
          return parseFloat(component);
        });
      }
    },
    
    dragTileMove: function(e){
      if(!this.playing) return false;
      
      this.touch.x2 = e.touches[0].pageX;
      this.touch.y2 = e.touches[0].pageY;
      
      this.deltaX = this.touch.x2 - this.touch.x1;
      this.deltaY = this.touch.y2 - this.touch.y1;
      
      // Respect current tile positioning
      var visibleX = this.originalTransform[0];
      var visibleY = this.originalTransform[1];
      
      // Restrict movement to tile width and height
      switch(this.moveTo) {
        case 'left':
          this.deltaX = Math.max(Math.min(this.deltaX, 0), -this.WIDTH);
          break;
        case 'right':
          this.deltaX = Math.min(Math.max(this.deltaX, 0), this.WIDTH);
          break;
        case 'top':
          this.deltaY = Math.max(Math.min(this.deltaY, 0), -this.HEIGHT);
          break;
        case 'bottom':
          this.deltaY = Math.min(Math.max(this.deltaY, 0), this.HEIGHT);
          break;
      }
      
      // Move only in one direction depending on how tiles are positioned
      if(this.horizontal) {
        visibleX += this.deltaX;
      } else {
        visibleY += this.deltaY;
      }
      
      $(this.el).css({ '-webkit-transform': 'translate(' + visibleX + 'px, ' + visibleY + 'px)'});
    },
    
    dragTileEnd: function(event){
      if(!this.playing) return false;
      
      if(Math.abs(this.deltaX) > this.WIDTH/2 || Math.abs(this.deltaY) > this.HEIGHT/2) {
        // Play the tile if it passes the half of its size
        this.model.play();
      } else {
        // Revert it back to original position
        $(this.el).anim({ translate: this.originalTransform[0] + 'px, ' + this.originalTransform[1] + 'px'}, 0.125, 'ease-out');
      }
      
      this.playing = false;
      this.originalTransform = [];
    },
    
  });
  
  /*
    Board consist of tiles
  */
  window.Board = Backbone.Collection.extend({
    
    SIZE: 4, // Matrix with SIZE x SIZE elements
    <commit_msg>Switched to translate3D to enable hardware acceleration in Mobile Safari<commit_after>// 
//  fifteens.js
//  
//  Created by <NAME> on 2011-04-10.
//  Copyright 2011 okonet.ru. All rights reserved.
// 

$(function(){
  
  /*
    Tile model and view
  */
  window.Tile = Backbone.Model.extend({
    
    initialize: function(){
      if (!this.get('empty')) {
        this.set({ empty: false });
      }  
    },
    
    isEmpty: function(){
      return this.get('empty');
    },
    
    play: function(){
      var board = this.collection;
      var tilePos = this.get('position');
      var emptyPos = board.getEmptyTile().get('position');
      
      board.getEmptyTile().set({ position: tilePos }, { silent: true });
      this.set({ position: emptyPos });
      game.set({ moves: game.get('moves') + 1 });
    },
    
    canBePlayed: function(){
      var boardSize = this.collection.SIZE;
      var tilePos = this.get('position');
      var emptyPos = this.collection.getEmptyTile().get('position');
      var delta = Math.abs(tilePos - emptyPos);
      
      if(delta == 1 || delta == boardSize) {
        // Empty is in first row. Previous tile can not be played
        if(emptyPos % boardSize == 0 && tilePos == (emptyPos - 1))
          return false;
        // Empty is in last row. Next tile can not be played
        else if((emptyPos + 1) % boardSize == 0 && tilePos == (emptyPos + 1))
          return false;
        else
          // If true, return useful data so we can use it in views
          return {
            real: (tilePos - emptyPos),
            delta: delta
          };
      } else {
        return false;
      }
    },

  });
  window.TileView = Backbone.View.extend({
    
    WIDTH: 144,
    HEIGHT: 136,
    
    tagName: 'li',
    
    className: 'b-tile',
    
    template: _.template("<p><%= label %></p>"),
    
    events: {
      'tap'        : 'playTile',
      'touchstart' : 'dragTileStart',
      'touchmove'  : 'dragTileMove',
      'touchend'   : 'dragTileEnd'
    },
    
    initialize: function() {
      _.bindAll(this, 'render', 'playTile', 'dragTileStart', 'dragTileMove', 'dragTileEnd');
      this.model.bind('change', this.render);
      this.model.view = this;
    },

    render: function() {
      tileData = this.model.toJSON();
      $(this.el).html(this.template(tileData));
      
      if(tileData.empty) $(this.el).addClass('b-tile_empty');
      
      var board = this.model.collection;
      
      var left = (tileData.position % board.SIZE) * this.WIDTH;
      var top = (Math.ceil((tileData.position + 1) / board.SIZE) - 1) * this.HEIGHT;
      
      var el = $(this.el);
      
      el.css({ 'z-index': tileData.position }).anim({ translate3d: left + 'px, ' + top + 'px, 0'}, 0.125, 'ease-out');
      
      return this;
    },
    
    playTile: function(){
      if(this.model.canBePlayed()) this.model.play();
    },
    
    dragTileStart: function(e){
      this.touch = {};
      this.touch.x1 = e.touches[0].pageX;
      this.touch.y1 = e.touches[0].pageY;
      
      var canBePlayed = this.model.canBePlayed();
      
      if(canBePlayed) {
        this.playing = true;
        this.horizontal = (canBePlayed.delta == 1) ? true : false;
        
        this.moveTo = (this.horizontal && canBePlayed.real < 0) ? 'right' : 
                      (this.horizontal && canBePlayed.real > 0)  ? 'left' : 
                      (!this.horizontal && canBePlayed.real < 0) ? 'bottom' : 
                      (!this.horizontal && canBePlayed.real > 0) ? 'top' : false;
        
        this.originalTransform = _.map($(this.el).css('-webkit-transform').replace('translate3d(','').split(','), function(component){
          return parseFloat(component);
        });
      }
    },
    
    dragTileMove: function(e){
      if(!this.playing) return false;
      
      this.touch.x2 = e.touches[0].pageX;
      this.touch.y2 = e.touches[0].pageY;
      
      this.deltaX = this.touch.x2 - this.touch.x1;
      this.deltaY = this.touch.y2 - this.touch.y1;
      
      // Respect current tile positioning
      var visibleX = this.originalTransform[0];
      var visibleY = this.originalTransform[1];
      
      // Restrict movement to tile width and height
      switch(this.moveTo) {
        case 'left':
          this.deltaX = Math.max(Math.min(this.deltaX, 0), -this.WIDTH);
          break;
        case 'right':
          this.deltaX = Math.min(Math.max(this.deltaX, 0), this.WIDTH);
          break;
        case 'top':
          this.deltaY = Math.max(Math.min(this.deltaY, 0), -this.HEIGHT);
          break;
        case 'bottom':
          this.deltaY = Math.min(Math.max(this.deltaY, 0), this.HEIGHT);
          break;
      }
      
      // Move only in one direction depending on how tiles are positioned
      if(this.horizontal) {
        visibleX += this.deltaX;
      } else {
        visibleY += this.deltaY;
      }
      
      $(this.el).css({ '-webkit-transform': 'translate3d(' + visibleX + 'px, ' + visibleY + 'px, 0)'});
    },
    
    dragTileEnd: function(event){
      if(!this.playing) return false;
      
      if(Math.abs(this.deltaX) > this.WIDTH/2 || Math.abs(this.deltaY) > this.HEIGHT/2) {
        // Play the tile if it passes the half of its size
        this.model.play();
      } else {
        // Revert it back to original position
        $(this.el).anim({ translate3D: this.originalTransform[0] + 'px, ' + this.originalTransform[1] + 'px, 0'}, 0.125, 'ease-out');
      }
      
      this.playing = false;
      this.originalTransform = [];
    },
    
  });
  
  /*
    Board consist of tiles
  */
  window.Board = Backbone.Collection.extend({
    
    SIZE: 4, // Matrix with SIZE x SIZE elements
    
{'fraction_non_alphanumeric': 0.15245024984658542, 'fraction_numerical': 0.011747172788638556, 'mean_word_length': 1.9258784303667607, 'pattern_counts': {'":': 0, '<': 16, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6300356', 'n_tokens_mistral': 3739, 'n_tokens_neox': 3596, 'n_words': 794}