<commit_before>/*
 * QuickBlox JavaScript SDK
 *
 * Proxy Module
 *
 */

// Browserify exports and dependencies
module.exports = ServiceProxy;
var isBrowser = typeof window !== "undefined" && window.jQuery;

var config = require('./qbConfig');

// For server-side applications through using npm package 'quickblox' you should include the following line
if(!isBrowser) var request = require('request');

function ServiceProxy() {
  this.qbInst = {
    config: config,
    session: null
  };
  if (config.debug) { console.log("ServiceProxy", this.qbInst); }
}

ServiceProxy.prototype.setSession = function(session) {
  this.qbInst.session = session;
};

ServiceProxy.prototype.getSession = function() {
  return this.qbInst.session;
};

ServiceProxy.prototype.ajax = function(params, callback) {
  if (config.debug) { console.log('ServiceProxy', params.type || 'GET', params); }
  var _this = this;
  var ajaxCall = {
    url: params.url,
    type: params.type || 'GET',
    dataType: params.dataType || 'json',
    data: params.data || ' ',
    timeout: config.timeout !== null ? config.timeout : null,
    beforeSend: function(jqXHR, settings) {
      if (config.debug) { console.log('ServiceProxy.ajax beforeSend', jqXHR, settings); }
      if (settings.url.indexOf('://' + config.endpoints.s3Bucket) === -1) {
        console.log('setting headers on request to ' + settings.url);
        if (_this.qbInst.session && _this.qbInst.session.token) {
          jqXHR.setRequestHeader('QB-Token', _this.qbInst.session.token);
        }
      }
    },
    success: function(data, status, jqHXR) {
      if (config.debug) { console.log('ServiceProxy.ajax success', data); }
      callback(null, data);
    },
    error: function(jqHXR, status, error) {
      if (config.debug) { console.log('ServiceProxy.ajax error', jqHXR.status, error, jqHXR.responseText); }
      var errorMsg = {
        code: jqHXR.status,
        status: status,
        message: error,
        detail: jqHXR.responseText
      };
      callback(errorMsg, null);
    }
  };

  if(!isBrowser) {
    if (ajaxCall.dataType === 'json') ajaxCall.json = ajaxCall.data;
    if (params.url.indexOf('://' + config.endpoints.s3Bucket) === -1 && _this.qbInst.session && _this.qbInst.session.token)
      ajaxCall.headers = { 'QB-Token' : _this.qbInst.session.token };
    ajaxCall.method = ajaxCall.type;
  }

  // Optional - for example 'multipart/form-data' when sending a file.
  // Default is 'application/x-www-form-urlencoded; charset=UTF-8'
  if (typeof params.contentType === 'boolean' || typeof params.contentType === 'string') { ajaxCall.contentType = params.contentType; }
  if (typeof params.processData === 'boolean') { ajaxCall.processData = params.processData; }

  if(isBrowser) {
    jQuery.ajax( ajaxCall );
  } else {
    request(ajaxCall, function(error, response, body) {
      if(!error) {
        ajaxCall.success(body);
      } else {
        ajaxCall.error(error, response.statusCode, body)
      }
    });
  }
};
<commit_msg>Removed redundant code<commit_after>/*
 * QuickBlox JavaScript SDK
 *
 * Proxy Module
 *
 */

// Browserify exports and dependencies
module.exports = ServiceProxy;
var isBrowser = typeof window !== "undefined" && window.jQuery;

var config = require('./qbConfig');

// For server-side applications through using npm package 'quickblox' you should include the following line
if(!isBrowser) var request = require('request');

function ServiceProxy() {
  this.qbInst = {
    config: config,
    session: null
  };
  if (config.debug) { console.log("ServiceProxy", this.qbInst); }
}

ServiceProxy.prototype.setSession = function(session) {
  this.qbInst.session = session;
};

ServiceProxy.prototype.getSession = function() {
  return this.qbInst.session;
};

ServiceProxy.prototype.ajax = function(params, callback) {
  if (config.debug) { console.log('ServiceProxy', params.type || 'GET', params); }
  var _this = this;
  var ajaxCall = {
    url: params.url,
    type: params.type || 'GET',
    dataType: params.dataType || 'json',
    data: params.data || ' ',
    timeout: config.timeout,
    beforeSend: function(jqXHR, settings) {
      if (config.debug) { console.log('ServiceProxy.ajax beforeSend', jqXHR, settings); }
      if (settings.url.indexOf('://' + config.endpoints.s3Bucket) === -1) {
        console.log('setting headers on request to ' + settings.url);
        if (_this.qbInst.session && _this.qbInst.session.token) {
          jqXHR.setRequestHeader('QB-Token', _this.qbInst.session.token);
        }
      }
    },
    success: function(data, status, jqHXR) {
      if (config.debug) { console.log('ServiceProxy.ajax success', data); }
      callback(null, data);
    },
    error: function(jqHXR, status, error) {
      if (config.debug) { console.log('ServiceProxy.ajax error', jqHXR.status, error, jqHXR.responseText); }
      var errorMsg = {
        code: jqHXR.status,
        status: status,
        message: error,
        detail: jqHXR.responseText
      };
      callback(errorMsg, null);
    }
  };

  if(!isBrowser) {
    if (ajaxCall.dataType === 'json') ajaxCall.json = ajaxCall.data;
    if (params.url.indexOf('://' + config.endpoints.s3Bucket) === -1 && _this.qbInst.session && _this.qbInst.session.token)
      ajaxCall.headers = { 'QB-Token' : _this.qbInst.session.token };
    ajaxCall.method = ajaxCall.type;
  }

  // Optional - for example 'multipart/form-data' when sending a file.
  // Default is 'application/x-www-form-urlencoded; charset=UTF-8'
  if (typeof params.contentType === 'boolean' || typeof params.contentType === 'string') { ajaxCall.contentType = params.contentType; }
  if (typeof params.processData === 'boolean') { ajaxCall.processData = params.processData; }

  if(isBrowser) {
    jQuery.ajax( ajaxCall );
  } else {
    request(ajaxCall, function(error, response, body) {
      if(!error) {
        ajaxCall.success(body);
      } else {
        ajaxCall.error(error, response.statusCode, body)
      }
    });
  }
};
<|endoftext|>


<commit_before>var saveMap = (function () {
    var formats = {
        original: {
            headerLength: 28,
            searchOffset: 4449,
            model: "maps/tiny.scx",
            modelSize: 120,
            extension: "scx"
        },
        hd: {
            headerLength: 61,
            searchOffset: 4449,
            model: "maps/tiny.aoe2scenario",
            modelSize: 120,
            extension: "aoe2scenario"
        }
    };

    var holders = document.getElementsByClassName("holder"),
        holdersDict = {};
    for (var i = 0; i < holders.length; i++) {
        holdersDict[holders[i].climate] = holders[i];
    }

    function addTerrains(map) {
        var size = map.length;
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                var tile = map[i][j];
                var terrain = 1;
                if (tile.climate) {
                    var imgs = holdersDict[tile.climate].getElementsByTagName("img");
                    var img = imgs[Math.random() * imgs.length | 0];
                    terrain = img.index;
                }
                tile.terrain = terrain;
            }
        }
        addBeaches(map);
        addElevation(map, +document.getElementById("sldMaxElevation").value);
    }

    function generateMap(map) {
        addTerrains(map);
        var size = map.length;
        var data = [size, 0, 0, 0, size, 0, 0, 0];
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                var tile = map[i][j];
                data.push(tile.terrain, tile.level, 0);
            }
        }
        return new Uint8Array(data);
    }

    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";

    function save(mapData, format) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', format.model);
        xhr.responseType = 'arraybuffer';
        xhr.onreadystatechange = function (e) {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                var buffer = new Uint8Array(xhr.response);
                var header = buffer.slice(0, format.headerLength),
                    compressed = buffer.slice(format.headerLength);
                var uncompressed = pako.inflate(compressed, {
                    windowBits: -15
                });
                var index = uncompressed.indexOf(format.modelSize, format.searchOffset);
                var length = 8 + 3 * format.modelSize * format.modelSize;

                var head = uncompressed.slice(0, index);
                var map = generateMap(mapData);
                var foot = uncompressed.slice(index + length);

                var together = new Uint8Array(head.byteLength + map.byteLength + foot.byteLength);
                together.set(head);
                together.set(map, head.byteLength);
                together.set(foot, head.byteLength + map.byteLength);

                var recompressed = pako.deflate(together, {
                    level: 9,
                    windowBits: -15
                });
                var blob = new Blob([header, recompressed]),
                    url = window.URL.createObjectURL(blob);
                a.href = url;
                a.download = "real_world_scenario." + format.extension;
                a.click();
                window.URL.revokeObjectURL(url);
            }
        }
        xhr.send();
    }
    save.format = formats;
    return save;
})();<commit_msg>fix IE Edge not saving<commit_after>var saveMap = (function () {
    var formats = {
        original: {
            headerLength: 28,
            searchOffset: 4449,
            model: "maps/tiny.scx",
            modelSize: 120,
            extension: "scx"
        },
        hd: {
            headerLength: 61,
            searchOffset: 4449,
            model: "maps/tiny.aoe2scenario",
            modelSize: 120,
            extension: "aoe2scenario"
        }
    };

    var holders = document.getElementsByClassName("holder"),
        holdersDict = {};
    for (var i = 0; i < holders.length; i++) {
        holdersDict[holders[i].climate] = holders[i];
    }

    function addTerrains(map) {
        var size = map.length;
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                var tile = map[i][j];
                var terrain = 1;
                if (tile.climate) {
                    var imgs = holdersDict[tile.climate].getElementsByTagName("img");
                    var img = imgs[Math.random() * imgs.length | 0];
                    terrain = img.index;
                }
                tile.terrain = terrain;
            }
        }
        addBeaches(map);
        addElevation(map, +document.getElementById("sldMaxElevation").value);
    }

    function generateMap(map) {
        addTerrains(map);
        var size = map.length;
        var data = [size, 0, 0, 0, size, 0, 0, 0];
        for (var i = 0; i < size; i++) {
            for (var j = 0; j < size; j++) {
                var tile = map[i][j];
                data.push(tile.terrain, tile.level, 0);
            }
        }
        return new Uint8Array(data);
    }

    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";

    function save(mapData, format) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', format.model);
        xhr.responseType = 'arraybuffer';
        xhr.onreadystatechange = function (e) {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                var buffer = new Uint8Array(xhr.response);
                var header = buffer.slice(0, format.headerLength),
                    compressed = buffer.slice(format.headerLength);
                var uncompressed = pako.inflate(compressed, {
                    windowBits: -15
                });
                var index = uncompressed.indexOf(format.modelSize, format.searchOffset);
                var length = 8 + 3 * format.modelSize * format.modelSize;

                var head = uncompressed.slice(0, index);
                var map = generateMap(mapData);
                var foot = uncompressed.slice(index + length);

                var together = new Uint8Array(head.byteLength + map.byteLength + foot.byteLength);
                together.set(head);
                together.set(map, head.byteLength);
                together.set(foot, head.byteLength + map.byteLength);

                var recompressed = pako.deflate(together, {
                    level: 9,
                    windowBits: -15
                });
                var blob = new Blob([header, recompressed]),
                    url = window.URL.createObjectURL(blob);
                a.href = url;
                a.download = "real_world_scenario." + format.extension;
                a.click();
                setTimeout(function () {
                    window.URL.revokeObjectURL(url);
                }, 100);
            }
        }
        xhr.send();
    }
    save.format = formats;
    return save;
})();<|endoftext|>


<commit_before>function Player(mark, isAI) {
  this.mark = mark;
  this.isAI = isAI;
}

Player.prototype.markSpace = function(space) {
  if (space.player === undefined) {
    space.player = this;
  }
}

function Space(xCoordinate, yCoordinate) {
  this.xCoordinate = xCoordinate;
  this.yCoordinate = yCoordinate;
  this.player;
}

Space.prototype.markedBy = function () {
  return this.player;
}

function Board () {
  this.nBoard = [];
  for (var i=1; i <= 3; i++) {
    for (var j=1; j <= 3; j++) {
      var space = new Space(i, j);
      this.nBoard.push(space);
    }
  }
}

Board.prototype.findSpace = function (x, y) {
  for(var indvSpace in this.nBoard) {
    if ((x === this.nBoard[indvSpace].xCoordinate) && (y === this.nBoard[indvSpace].yCoordinate)){
      return this.nBoard[indvSpace];
    }
  }
};

Board.prototype.threeInARow = function(player) {
    var rows = [[0,4,8],[2,4,6],[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8]];
    var board = this;
    // console.log("we are in threeInARow");
    // console.log(board.nBoard[0].markedBy());
    // console.log("what the hell is player");
    // console.log(player)
    return rows.some(function(winningCombo) {
      return (board.nBoard[winningCombo[0]].markedBy() === player && board.nBoard[winningCombo[1]].markedBy() === player && board.nBoard[winningCombo[2]].markedBy() === player);
    });
  }

function Game(multiplayer) {
  this.multiplayer = multiplayer;
  this.players = [];
  this.currentTurn = Math.floor(Math.random() * 2) ;
  this.board = new Board();

  this.players.push(new Player("X", false));
  if(multiplayer === true) {
    this.players.push(new Player("O", false));
  } else {
    this.players.push(new Player("O", true));
  }
}

  Game.prototype.changeTurn = function () {
    if(this.currentTurn === 0) {
      this.currentTurn = 1;
      return 1;
    } else {
      this.currentTurn = 0;
      return 0;
    }
  }

  Game.prototype.findWinner = function() {
    if ((this.board.findSpace(1, 1).markedBy() && this.board.findSpace(2, 2).markedBy() && this.board.findSpace(3, 3).markedBy()) || (this.board.findSpace(3, 1).markedBy() && this.board.findSpace(2, 2).markedBy() && this.board.findSpace(1, 3).markedBy())) {
      return this.board.findSpace(2, 2).markedBy();
    }
    //debugger;
    var check = undefined;
    var notMatch = true;
    for (var i = 1; i <= 3; i++) {
      for (var j = 1; j <= 3; j++) {
        if (this.board.findSpace(i, j).markedBy() != undefined) {
          if (check === undefined) {
            check = this.board.findSpace(i, j).markedBy().mark;
          } else if (check = this.board.findSpace(i, j).markedBy().mark) {
            notMatch = false;
          } else {
            notMatch = true;
          }
        }
      }
      if (notMatch = false) {
        return this.board.findSpace(i, j-1).markedBy();
      }
      check = undefined;
    }

    for (var i = 1; i <= 3; i++) {
      for (var j = 1; j <= 3; j++) {
        if (this.board.findSpace(j, i).markedBy() != undefined) {
          if (check === undefined) {
            check = this.board.findSpace(j, i).markedBy().mark;
          } else if (check = this.board.findSpace(j, i).markedBy().mark) {
            notMatch = false;
          } else {
            notMatch = true;
          }
        }
      }
    if (!notMatch) {
      return this.board.findSpace(j-1, i).markedBy();
    }
    check = undefined;
  }
}

$(document).ready(function() {
  $("form#new-game").submit(function(event) {
    event.preventDefault();
    new_game = new Game();
    console.log(new_game)
  });

  $('.row').on("click", ".squares", function() {
    space = (new_game.board.nBoard[parseInt(this.id)]);
    turn = new_game.changeTurn();
    player = new_game.players[turn];
    player.markSpace(space);
    $(this).text(player.mark).removeClass("squares");

    if (new_game.board.threeInARow(player)) {
      alert(player.mark + ' is the winner!');
    }

  });
});
<commit_msg>Refactor winner alert<commit_after>function Player(mark, isAI) {
  this.mark = mark;
  this.isAI = isAI;
}

Player.prototype.markSpace = function(space) {
  if (space.player === undefined) {
    space.player = this;
  }
}

function Space(xCoordinate, yCoordinate) {
  this.xCoordinate = xCoordinate;
  this.yCoordinate = yCoordinate;
  this.player;
}

Space.prototype.markedBy = function () {
  return this.player;
}

function Board () {
  this.nBoard = [];
  for (var i=1; i <= 3; i++) {
    for (var j=1; j <= 3; j++) {
      var space = new Space(i, j);
      this.nBoard.push(space);
    }
  }
}

Board.prototype.findSpace = function (x, y) {
  for(var indvSpace in this.nBoard) {
    if ((x === this.nBoard[indvSpace].xCoordinate) && (y === this.nBoard[indvSpace].yCoordinate)){
      return this.nBoard[indvSpace];
    }
  }
};

Board.prototype.threeInARow = function(player) {
    var rows = [[0,4,8],[2,4,6],[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8]];
    var board = this;
    return rows.some(function(winningCombo) {
      return (board.nBoard[winningCombo[0]].markedBy() === player && board.nBoard[winningCombo[1]].markedBy() === player && board.nBoard[winningCombo[2]].markedBy() === player);
    });
  }

function Game(multiplayer) {
  this.multiplayer = multiplayer;
  this.players = [];
  this.currentTurn = Math.floor(Math.random() * 2) ;
  this.board = new Board();

  this.players.push(new Player("X", false));
  if(multiplayer === true) {
    this.players.push(new Player("O", false));
  } else {
    this.players.push(new Player("O", true));
  }
}

  Game.prototype.changeTurn = function () {
    if(this.currentTurn === 0) {
      this.currentTurn = 1;
      return 1;
    } else {
      this.currentTurn = 0;
      return 0;
    }
  }

$(document).ready(function() {
  $("form#new-game").submit(function(event) {
    event.preventDefault();
    new_game = new Game();
    console.log(new_game)
  });

  $('.row').on("click", ".squares", function() {
    space = (new_game.board.nBoard[parseInt(this.id)]);
    turn = new_game.changeTurn();
    player = new_game.players[turn];
    player.markSpace(space);
    $(this).text(player.mark).removeClass("squares");

    if (new_game.board.threeInARow(player)) {
        if(confirm(player.mark + ' is the winner!')) {
          location.reload();
          console.log(new_game.board.nBoard)
        }
    }

  });
});
<|endoftext|>


<commit_before>
function simple_hash(s) {
 return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

 function report_js_error(msg, url, linenumber) {
  var stuff=" URL: "+url+" - "+msg+"; line: "+linenumber;
  console.log('JAVASCRIPT ERROR: '+stuff);
  var tmp = new Image();
  tmp.src = ROOTHTML+"write_error.php?error="+encodeURIComponent(stuff);
  return true;
 }

window.onerror=report_js_error;

var bV=parseInt(navigator.appVersion);
NS4=(document.layers) ? true : false;
IE4=((document.all)&&(bV>=4))?true:false;

//[#if ("1"=="<#DEBUG_TEMPLATES#>")#]
//[#inc debug_templates.js#]
//[#endif#]

// <AJAX>

var Letters=new Array('%C0','%C1','%C2','%C3','%C4','%C5','%C6','%C7','%C8','%C9','%CA','%CB','%CC','%CD','%CE','%CF','%D0','%D1','%D2','%D3','%D4','%D5','%D6','%D7','%D8','%D9','%DA','%DB','%DC','%DD','%DE','%DF','%E0','%E1','%E2','%E3','%E4','%E5','%E6','%E7','%E8','%E9','%EA','%EB','%EC','%ED','%EE','%EF','%F0','%F1','%F2','%F3','%F4','%F5','%F6','%F7','%F8','%F9','%FA','%FB','%FC','%FD','%FE','%FF','%A8','%B8');
var flashing=0;

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

function Win2Escape(AStr){
var Result='';
for(var i=0;i<AStr.length;i++)
if(AStr.charAt(i)>='�' && AStr.charAt(i)<='�')
Result+=Letters[AStr.charCodeAt(i)-0x0410];
else if(AStr.charAt(i)=='�')
Result+=Letters[64];
else if(AStr.charAt(i)=='�')
Result+=Letters[65];
else if(AStr.charAt(i)=='=')
Result+='%3D';
else if(AStr.charAt(i)=='&')
Result+='%26';
else
Result+=AStr.charAt(i);
return Result;
}//Win2Escape

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

function URLencode(sStr) {
    return (Win2Escape(sStr)).replace(/\+/g, '%2C').replace(/\"/g,'%22').replace(/\'/g, '%27');
}

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

function startFlashing(block_id) {

 layer = document.getElementById(block_id);
 if (flashing==1) {
  layer.style.borderWidth='1px';
  layer.style.borderColor='#000000';
  if (layer.style.borderStyle.indexOf('none') == -1) {
   //alert(layer.style.borderStyle);
   layer.style.borderStyle='none';
  } else {
   layer.style.borderStyle='dotted';
  }
  window.setTimeout("startFlashing('"+block_id+"');", 100);

 } else {
  layer.style.borderStyle='none';
  layer.style.borderWidth='0px';
 }

}

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

 function AJAXRequest(url, ready_function, first_param, proc_function) {

  proc_function = proc_function || '';
  first_param = first_param || '';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("GET", url,true);
  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    eval(ready_function+'(\''+first_param+'\', xmlhttp.responseText);');
   }
  }
  if (proc_function) {
   eval(proc_function+'();');
  }
  xmlhttp.send(null);

  return false;
 }

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

 function getBlockDataForm(block_id, form) {
  params='';
  for(i=0;i<form.elements.length;i++) {
   if ((form.elements[i].type!='radio' && form.elements[i].type!='checkbox') || form.elements[i].checked) {
    params+='&'+form.elements[i].name+'='+URLencode(form.elements[i].value);
   }
  }
  //alert(params);
  url=form.action;

 layer = document.getElementById(block_id);
 old_data=layer.innerHTML;

 flashing=1;
 startFlashing(block_id);

// layer.innerHTML='Loading please wait...';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }

  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    flashing=0;
    layer.innerHTML=xmlhttp.responseText;
    layer.style.borderStyle='none';
   }
  }

  if (form.method=='post') {
   xmlhttp.open("POST", url, true);
   xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
   xmlhttp.send(params+'&filterblock='+block_id);
  } else {
   xmlhttp.open("GET", url+params+'&filterblock='+block_id,true);
   xmlhttp.send(null);
  }

  return false;

 }

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

 function getBlockData(block_id, url) {
  layer = document.getElementById(block_id);
  old_data=layer.innerHTML;

  flashing=1;
  startFlashing(block_id);
//  return false;
  //layer.innerHTML='Loading please wait...';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("GET", url+'&filterblock='+block_id,true);
  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    flashing=0;
    layer.style.borderStyle='none';
    layer.innerHTML=xmlhttp.responseText;
   }
  }
  xmlhttp.send(null);
  return false;
 }

 function callMethod(method_name, optional_params) {
  if (typeof optional_params === 'undefined') { optional_params = ''; }
  var url=ROOTHTML;
  url+='objects/?method='+encodeURIComponent(method_name)+'&'+optional_params;
  $.ajax({
   url: url
  }).done(function(data) {
    //alert(data);
   });
 }

 function runScript(script_name, optional_params) {
  if (typeof optional_params === 'undefined') { optional_params = ''; }
  var url=ROOTHTML;
  url+='objects/?script='+encodeURIComponent(script_name)+'&'+optional_params;
  $.ajax({
   url: url
  }).done(function(data) {
    //alert(data);
   });
 }

 function ajaxGetGlobal(varname, id, timeout) {
  var url=ROOTHTML;
  url+='?md=application&action=ajaxgetglobal&var='+encodeURIComponent(varname);
  $.ajax({
   url: url
  }).done(function(data) {
   var obj=jQuery.parseJSON(data);
    if (obj.DATA) {
      $('#'+id).html(obj.DATA);
    }
   });
  if (timeout>0) {
   window.setTimeout('ajaxGetGlobal("'+varname+'", "'+id+'", '+timeout+');', timeout);
  }
  return false;
 }

 function ajaxSetGlobal(varname, value) {
  var url=ROOTHTML;
  url+='?md=application&action=ajaxsetglobal&var='+encodeURIComponent(varname)+'&value='+encodeURIComponent(value);
  $.ajax({
   url: url
  }).done(function(data) {
   var obj=jQuery.parseJSON(data);
    if (obj.DATA) {
      //
    }
   });
  return false;
 }

 function setGlobal(varname, value) {
  ajaxSetGlobal(varname, value);
 }

function getCookie(Name) {
 var search = Name + "="
 if (document.cookie.length > 0)
 { // if there are any cookies
  offset = document.cookie.indexOf(search)
  if (offset != -1) { // if cookie exists
   offset += search.length          // set index of beginning of value
   end = document.cookie.indexOf(";", offset)          // set index of end of cookie value
   if (end == -1) end = document.cookie.length
   return unescape(document.cookie.substring(offset, end))
  }
 }
}

function setCookie(name, value) {
 var expire = "0, 01-01-2099 00:00:00 GMT"; // fix it someday in 2099 :)
 document.cookie = name + "=" + escape(value) + "; expires=" + expire + "; path=/";
}

var ajaxManager = (function() {
 var requests = [];

 return {
  addReq:  function(opt) {
   if( !($.inArray(opt, requests) > -1) )
    requests.push(opt);
  },
  removeReq:  function(opt) {
   if( $.inArray(opt, requests) > -1 )
    requests.splice($.inArray(opt, requests), 1);
  },
  run: function() {
   var self = this,
       oriSuc;

   if( requests.length ) {
    oriSuc = requests[0].complete;

    requests[0].complete = function() {
     if( typeof(oriSuc) === 'function' ) oriSuc();
     requests.shift();
     self.run.apply(self, []);
    };

    $.ajax(requests[0]);
   } else {
    self.tid = setTimeout(function() {
     self.run.apply(self, []);
    }, 1000);
   }
  },
  stop:  function() {
   requests = [];
   clearTimeout(this.tid);
  }
 };
}());

// </AJAX>
<commit_msg>Update scripts.js<commit_after>//Конвектор времени
function twoDigits(num) {
	if(num == 0) num = 1;
	return ('0' + num).slice(-2);
}

function secondsToHms(d) {
	d = Number(d);
	var h = Math.floor(d / 3600);
	var m = Math.floor(d % 3600 / 60);
	var s = Math.floor(d % 3600 % 60);

	var hDisplay = h > 0 ? h + " час. " : "";
	var mDisplay = m > 0 ? m + " мин. " : "";
	var sDisplay = !h ? (s > 0 ? s + " сек. " : "") : "";
	return hDisplay + mDisplay + sDisplay;
}

function simple_hash(s) {
 return s.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
}

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

 function report_js_error(msg, url, linenumber) {
  var stuff=" URL: "+url+" - "+msg+"; line: "+linenumber;
  console.log('JAVASCRIPT ERROR: '+stuff);
  var tmp = new Image();
  tmp.src = ROOTHTML+"write_error.php?error="+encodeURIComponent(stuff);
  return true;
 }

window.onerror=report_js_error;

var bV=parseInt(navigator.appVersion);
NS4=(document.layers) ? true : false;
IE4=((document.all)&&(bV>=4))?true:false;

//[#if ("1"=="<#DEBUG_TEMPLATES#>")#]
//[#inc debug_templates.js#]
//[#endif#]

// <AJAX>

var Letters=new Array('%C0','%C1','%C2','%C3','%C4','%C5','%C6','%C7','%C8','%C9','%CA','%CB','%CC','%CD','%CE','%CF','%D0','%D1','%D2','%D3','%D4','%D5','%D6','%D7','%D8','%D9','%DA','%DB','%DC','%DD','%DE','%DF','%E0','%E1','%E2','%E3','%E4','%E5','%E6','%E7','%E8','%E9','%EA','%EB','%EC','%ED','%EE','%EF','%F0','%F1','%F2','%F3','%F4','%F5','%F6','%F7','%F8','%F9','%FA','%FB','%FC','%FD','%FE','%FF','%A8','%B8');
var flashing=0;

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

function Win2Escape(AStr){
var Result='';
for(var i=0;i<AStr.length;i++)
if(AStr.charAt(i)>='�' && AStr.charAt(i)<='�')
Result+=Letters[AStr.charCodeAt(i)-0x0410];
else if(AStr.charAt(i)=='�')
Result+=Letters[64];
else if(AStr.charAt(i)=='�')
Result+=Letters[65];
else if(AStr.charAt(i)=='=')
Result+='%3D';
else if(AStr.charAt(i)=='&')
Result+='%26';
else
Result+=AStr.charAt(i);
return Result;
}//Win2Escape

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

function URLencode(sStr) {
    return (Win2Escape(sStr)).replace(/\+/g, '%2C').replace(/\"/g,'%22').replace(/\'/g, '%27');
}

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

function startFlashing(block_id) {

 layer = document.getElementById(block_id);
 if (flashing==1) {
  layer.style.borderWidth='1px';
  layer.style.borderColor='#000000';
  if (layer.style.borderStyle.indexOf('none') == -1) {
   //alert(layer.style.borderStyle);
   layer.style.borderStyle='none';
  } else {
   layer.style.borderStyle='dotted';
  }
  window.setTimeout("startFlashing('"+block_id+"');", 100);

 } else {
  layer.style.borderStyle='none';
  layer.style.borderWidth='0px';
 }

}

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

 function AJAXRequest(url, ready_function, first_param, proc_function) {

  proc_function = proc_function || '';
  first_param = first_param || '';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("GET", url,true);
  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    eval(ready_function+'(\''+first_param+'\', xmlhttp.responseText);');
   }
  }
  if (proc_function) {
   eval(proc_function+'();');
  }
  xmlhttp.send(null);

  return false;
 }

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

 function getBlockDataForm(block_id, form) {
  params='';
  for(i=0;i<form.elements.length;i++) {
   if ((form.elements[i].type!='radio' && form.elements[i].type!='checkbox') || form.elements[i].checked) {
    params+='&'+form.elements[i].name+'='+URLencode(form.elements[i].value);
   }
  }
  //alert(params);
  url=form.action;

 layer = document.getElementById(block_id);
 old_data=layer.innerHTML;

 flashing=1;
 startFlashing(block_id);

// layer.innerHTML='Loading please wait...';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }

  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    flashing=0;
    layer.innerHTML=xmlhttp.responseText;
    layer.style.borderStyle='none';
   }
  }

  if (form.method=='post') {
   xmlhttp.open("POST", url, true);
   xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
   xmlhttp.send(params+'&filterblock='+block_id);
  } else {
   xmlhttp.open("GET", url+params+'&filterblock='+block_id,true);
   xmlhttp.send(null);
  }

  return false;

 }

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

 function getBlockData(block_id, url) {
  layer = document.getElementById(block_id);
  old_data=layer.innerHTML;

  flashing=1;
  startFlashing(block_id);
//  return false;
  //layer.innerHTML='Loading please wait...';

 var xmlhttp=false;

/*@cc_on @*/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
 try {
  xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
 } catch (e) {
  try {
   xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (E) {
   xmlhttp = false;
  }
 }
@end @*/

  if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
   xmlhttp = new XMLHttpRequest();
  }
  xmlhttp.open("GET", url+'&filterblock='+block_id,true);
  xmlhttp.onreadystatechange=function() {
   if (xmlhttp.readyState==4) {
    flashing=0;
    layer.style.borderStyle='none';
    layer.innerHTML=xmlhttp.responseText;
   }
  }
  xmlhttp.send(null);
  return false;
 }

 function callMethod(method_name, optional_params) {
  if (typeof optional_params === 'undefined') { optional_params = ''; }
  var url=ROOTHTML;
  url+='objects/?method='+encodeURIComponent(method_name)+'&'+optional_params;
  $.ajax({
   url: url
  }).done(function(data) {
    //alert(data);
   });
 }

 function runScript(script_name, optional_params) {
  if (typeof optional_params === 'undefined') { optional_params = ''; }
  var url=ROOTHTML;
  url+='objects/?script='+encodeURIComponent(script_name)+'&'+optional_params;
  $.ajax({
   url: url
  }).done(function(data) {
    //alert(data);
   });
 }

 function ajaxGetGlobal(varname, id, timeout) {
  var url=ROOTHTML;
  url+='?md=application&action=ajaxgetglobal&var='+encodeURIComponent(varname);
  $.ajax({
   url: url
  }).done(function(data) {
   var obj=jQuery.parseJSON(data);
    if (obj.DATA) {
      $('#'+id).html(obj.DATA);
    }
   });
  if (timeout>0) {
   window.setTimeout('ajaxGetGlobal("'+varname+'", "'+id+'", '+timeout+');', timeout);
  }
  return false;
 }

 function ajaxSetGlobal(varname, value) {
  var url=ROOTHTML;
  url+='?md=application&action=ajaxsetglobal&var='+encodeURIComponent(varname)+'&value='+encodeURIComponent(value);
  $.ajax({
   url: url
  }).done(function(data) {
   var obj=jQuery.parseJSON(data);
    if (obj.DATA) {
      //
    }
   });
  return false;
 }

 function setGlobal(varname, value) {
  ajaxSetGlobal(varname, value);
 }

function getCookie(Name) {
 var search = Name + "="
 if (document.cookie.length > 0)
 { // if there are any cookies
  offset = document.cookie.indexOf(search)
  if (offset != -1) { // if cookie exists
   offset += search.length          // set index of beginning of value
   end = document.cookie.indexOf(";", offset)          // set index of end of cookie value
   if (end == -1) end = document.cookie.length
   return unescape(document.cookie.substring(offset, end))
  }
 }
}

function setCookie(name, value) {
 var expire = "0, 01-01-2099 00:00:00 GMT"; // fix it someday in 2099 :)
 document.cookie = name + "=" + escape(value) + "; expires=" + expire + "; path=/";
}

var ajaxManager = (function() {
 var requests = [];

 return {
  addReq:  function(opt) {
   if( !($.inArray(opt, requests) > -1) )
    requests.push(opt);
  },
  removeReq:  function(opt) {
   if( $.inArray(opt, requests) > -1 )
    requests.splice($.inArray(opt, requests), 1);
  },
  run: function() {
   var self = this,
       oriSuc;

   if( requests.length ) {
    oriSuc = requests[0].complete;

    requests[0].complete = function() {
     if( typeof(oriSuc) === 'function' ) oriSuc();
     requests.shift();
     self.run.apply(self, []);
    };

    $.ajax(requests[0]);
   } else {
    self.tid = setTimeout(function() {
     self.run.apply(self, []);
    }, 1000);
   }
  },
  stop:  function() {
   requests = [];
   clearTimeout(this.tid);
  }
 };
}());

// </AJAX>
<|endoftext|>


<commit_before>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');

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

module.exports = class tidebit extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'tidebit',
            'name': 'TideBit',
            'countries': [ 'HK' ],
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'fetchDepositAddress': true,
                'CORS': true,
                'fetchTickers': true,
                'fetchOHLCV': true,
                'withdraw': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '2h': '120',
                '4h': '240',
                '12h': '720',
                '1d': '1440',
                '3d': '4320',
                '1w': '10080',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/39034921-e3acf016-4480-11e8-9945-a6086a1082fe.jpg',
                'api': 'https://www.tidebit.com',
                'www': 'https://www.tidebit.com',
                'doc': [
                    'https://www.tidebit.com/documents/api/guide',
                    'https://www.tidebit.com/swagger/#/default',
                ],
                'referral': 'http://bit.ly/2IX0LrM',
            },
            'api': {
                'public': {
                    'get': [
                        'markets',
                        'tickers',
                        'tickers/{market}',
                        'timestamp',
                        'trades',
                        'trades/{market}',
                        'order_book',
                        'order',
                        'k_with_pending_trades',
                        'k',
                        'depth',
                    ],
                    'post': [],
                },
                'private': {
                    'get': [
                        'addresses/{address}',
                        'deposits/history',
                        'deposits/get_deposit',
                        'deposits/deposit_address',
                        'historys/orders',
                        'historys/vouchers',
                        'historys/accounts',
                        'historys/snapshots',
                        'linkage/get_status',
                        'members/me',
                        'order',
                        'orders',
                        'partners/orders/{id}/trades',
                        'referral_commissions/get_undeposited',
                        'referral_commissions/get_graph_data',
                        'trades/my',
                        'withdraws/bind_account_list',
                        'withdraws/get_withdraw_account',
                        'withdraws/fetch_bind_info',
                    ],
                    'post': [
                        'deposits/deposit_cash',
                        'favorite_markets/update',
                        'order/delete',
                        'orders',
                        'orders/multi',
                        'orders/clear',
                        'referral_commissions/deposit',
                        'withdraws/apply',
                        'withdraws/bind_bank',
                        'withdraws/bind_address',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.2 / 100,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': true,
                    'withdraw': {}, // There is only 1% fee on withdrawals to your bank account.
                },
            },
            'exceptions': {
                '2002': InsufficientFunds,
                '2003': OrderNotFound,
            },
        });
    }

    async fetchDepositAddress (code, params = {}) {
        await this.loadMarkets ();
        let currency = this.currency (code);
        let response = await this.privateGetDepositAddress (this.extend ({
            'currency': currency['id'],
        }, params));
        if ('success' in response) {
            if (response['success']) {
                let address = this.safeString (response, 'address');
                let tag = this.safeString (response, 'addressTag');
                return {
                    'currency': code,
                    'address': this.checkAddress (address),
                    'tag': tag,
                    'info': response,
                };
            }
        }
    }

    async fetchMarkets (params = {}) {
        let markets = await this.publicGetMarkets ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'];
            let symbol = market['name'];
            let [ baseId, quoteId ] = symbol.split ('/');
            let base = this.commonCurrencyCode (baseId);
            let quote = this.commonCurrencyCode (quoteId);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetMembersMe ();
        let balances = response['accounts'];
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currencyId = balance['currency'];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id)
                code = this.currencies_by_id[currencyId]['code'];
            let account = {
                'free': parseFloat (balance['balance']),
                'used': parseFloat (balance['locked']),
                'total': 0.0,
            };
            account['total'] = this.sum (account['free'], account['used']);
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'market': market['id'],
        };
        if (limit === undefined)
            request['limit'] = limit; // default = 300
        request['market'] = market['id'];
        let orderbook = await this.publicGetDepth (this.extend (request, params));
        let timestamp = orderbook['timestamp'] * 1000;
        return this.parseOrderBook (orderbook, timestamp);
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = ticker['at'] * 1000;
        ticker = ticker['ticker'];
        let symbol = undefined;
        if (market !== undefined)
            symbol = market['symbol'];
        let last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'ask': this.safeFloat (ticker, 'sell'),
            'bidVolume': undefined,
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'previousClose': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetTickers (params);
        let ids = Object.keys (tickers);
        let result = {};
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let market = undefined;
            let symbol = id;
            if (id in this.markets_by_id) {
                market = this.markets_by_id[id];
                symbol = market['symbol'];
            } else {
                let base = id.slice (0, 3);
                let quote = id.slice (3, 6);
                base = base.toUpperCase ();
                quote = quote.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                symbol = base + '/' + quote;
            }
            let ticker = tickers[id];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

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

    parseTrade (trade, market = undefined) {
        let timestamp = this.parse8601 (trade['created_at']);
        return {
            'id': trade['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': undefined,
            'price': this.safeFloat (trade, 'price'),
            'amount': this.safeFloat (trade, 'volume'),
            'cost': this.safeFloat (trade, 'funds'),
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetTrades (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv[0] * 1000,
            ohlcv[1],
            ohlcv[2],
            ohlcv[3],
            ohlcv[4],
            ohlcv[5],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        if (limit === undefined)
            limit = 30; // default is 30
        let request = {
            'market': market['id'],
            'period': this.timeframes[timeframe],
            'limit': limit,
        };
        if (since !== undefined) {
            request['timestamp'] = since;
        } else {
            request['timestamp'] = 1800000;
        }
        let response = await this.publicGetK (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        } else {
            let marketId = order['market'];
            symbol = this.markets_by_id[marketId]['symbol'];
        }
        let timestamp = this.parse8601 (order['created_at']);
        let state = order['state'];
        let status = undefined;
        if (state === 'done') {
            status = 'closed';
        } else if (state === 'wait') {
            status = 'open';
        } else if (state === 'cancel') {
            status = 'canceled';
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': order['ord_type'],
            'side': order['side'],
            'price': this.safeFloat (order, 'price'),
            'amount': this.safeFloat (order, 'volume'),
            'filled': this.safeFloat (order, 'executed_volume'),
            'remaining': this.safeFloat (order, 'remaining_volume'),
            'trades': undefined,
            'fee': undefined,
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'market': this.marketId (symbol),
            'side': side,
            'volume': amount.toString (),
            'ord_type': type,
        };
        if (type === 'limit') {
            request['price'] = price.toString ();
        }
        let response = await this.privatePostOrders (this.extend (request, params));
        let market = this.markets_by_id[response['market']];
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePostOrderDelete ({ 'id': id });
        let order = this.parseOrder (result);
        let status = order['status'];
        if (status === 'closed' || status === 'canceled') {
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        }
        return order;
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        let currency = this.currency (code);
        let id = this.safeString (params, 'id');
        if (id === undefined) {
            throw new ExchangeError (this.id + ' withdraw() requires an extra id param (withdraw account id according to withdraws/bind_account_list endpoint');
        }
        let request = {
            'id': id,
            'currency_type': 'coin', // or 'cash'
            'currency': currency.toLowerCase (),
            'body': amount,
            // 'address': address, // they don't allow withdrawing to direct addresses?
        };
        if (tag !== undefined) {
            request['memo'] = tag;
        }
        let result = await this.privatePostWithdrawsApply (this.extend (request, params));
        return {
            'info': result,
            'id': undefined,
        };
    }

    nonce () {
        return this.milliseconds ();
    }

    encodeParams (params) {
        return this.urlencode (this.keysort (params));
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + 'api/' + this.version + '/' + this.implodeParams (path, params) + '.json';
        let query = this.omit (params, this.extractParams (path));
        let url = this.urls['api'] + request;
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let sortedByKey = this.keysort (this.extend ({
                'access_key': this.apiKey,
                'tonce': nonce,
            }, params));
            let query = this.urlencode (sortedByKey);
            let payload = method + '|' + request + '|' + query;
            let signature = this.hmac (this.encode (payload), this.encode (this.secret));
            let suffix = query + '&signature=' + signature;
            if (method === 'GET') {
                url += '?' + suffix;
            } else {
                body = suffix;
                headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body, response) {
        if (code === 400) {
            const error = this.safeValue (response, 'error');
            const errorCode = this.safeString (error, 'code');
            const feedback = this.id + ' ' + this.json (response);
            const exceptions = this.exceptions;
            if (errorCode in exceptions) {
                throw new exceptions[errorCode] (feedback);
            }
            // fallback to default error handler
        }
    }
};
<commit_msg>tidebit cleanup for eslint curly<commit_after>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');

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

module.exports = class tidebit extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'tidebit',
            'name': 'TideBit',
            'countries': [ 'HK' ],
            'rateLimit': 1000,
            'version': 'v2',
            'has': {
                'fetchDepositAddress': true,
                'CORS': true,
                'fetchTickers': true,
                'fetchOHLCV': true,
                'withdraw': true,
            },
            'timeframes': {
                '1m': '1',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '2h': '120',
                '4h': '240',
                '12h': '720',
                '1d': '1440',
                '3d': '4320',
                '1w': '10080',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/39034921-e3acf016-4480-11e8-9945-a6086a1082fe.jpg',
                'api': 'https://www.tidebit.com',
                'www': 'https://www.tidebit.com',
                'doc': [
                    'https://www.tidebit.com/documents/api/guide',
                    'https://www.tidebit.com/swagger/#/default',
                ],
                'referral': 'http://bit.ly/2IX0LrM',
            },
            'api': {
                'public': {
                    'get': [
                        'markets',
                        'tickers',
                        'tickers/{market}',
                        'timestamp',
                        'trades',
                        'trades/{market}',
                        'order_book',
                        'order',
                        'k_with_pending_trades',
                        'k',
                        'depth',
                    ],
                    'post': [],
                },
                'private': {
                    'get': [
                        'addresses/{address}',
                        'deposits/history',
                        'deposits/get_deposit',
                        'deposits/deposit_address',
                        'historys/orders',
                        'historys/vouchers',
                        'historys/accounts',
                        'historys/snapshots',
                        'linkage/get_status',
                        'members/me',
                        'order',
                        'orders',
                        'partners/orders/{id}/trades',
                        'referral_commissions/get_undeposited',
                        'referral_commissions/get_graph_data',
                        'trades/my',
                        'withdraws/bind_account_list',
                        'withdraws/get_withdraw_account',
                        'withdraws/fetch_bind_info',
                    ],
                    'post': [
                        'deposits/deposit_cash',
                        'favorite_markets/update',
                        'order/delete',
                        'orders',
                        'orders/multi',
                        'orders/clear',
                        'referral_commissions/deposit',
                        'withdraws/apply',
                        'withdraws/bind_bank',
                        'withdraws/bind_address',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'maker': 0.2 / 100,
                    'taker': 0.2 / 100,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': true,
                    'withdraw': {}, // There is only 1% fee on withdrawals to your bank account.
                },
            },
            'exceptions': {
                '2002': InsufficientFunds,
                '2003': OrderNotFound,
            },
        });
    }

    async fetchDepositAddress (code, params = {}) {
        await this.loadMarkets ();
        let currency = this.currency (code);
        let response = await this.privateGetDepositAddress (this.extend ({
            'currency': currency['id'],
        }, params));
        if ('success' in response) {
            if (response['success']) {
                let address = this.safeString (response, 'address');
                let tag = this.safeString (response, 'addressTag');
                return {
                    'currency': code,
                    'address': this.checkAddress (address),
                    'tag': tag,
                    'info': response,
                };
            }
        }
    }

    async fetchMarkets (params = {}) {
        let markets = await this.publicGetMarkets ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'];
            let symbol = market['name'];
            let [ baseId, quoteId ] = symbol.split ('/');
            let base = this.commonCurrencyCode (baseId);
            let quote = this.commonCurrencyCode (quoteId);
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetMembersMe ();
        let balances = response['accounts'];
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currencyId = balance['currency'];
            let code = currencyId.toUpperCase ();
            if (currencyId in this.currencies_by_id) {
                code = this.currencies_by_id[currencyId]['code'];
            }
            let account = {
                'free': parseFloat (balance['balance']),
                'used': parseFloat (balance['locked']),
                'total': 0.0,
            };
            account['total'] = this.sum (account['free'], account['used']);
            result[code] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'market': market['id'],
        };
        if (limit === undefined) {
            request['limit'] = limit; // default = 300
        }
        request['market'] = market['id'];
        let orderbook = await this.publicGetDepth (this.extend (request, params));
        let timestamp = orderbook['timestamp'] * 1000;
        return this.parseOrderBook (orderbook, timestamp);
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = ticker['at'] * 1000;
        ticker = ticker['ticker'];
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        }
        let last = this.safeFloat (ticker, 'last');
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high'),
            'low': this.safeFloat (ticker, 'low'),
            'bid': this.safeFloat (ticker, 'buy'),
            'ask': this.safeFloat (ticker, 'sell'),
            'bidVolume': undefined,
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'previousClose': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'vol'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetTickers (params);
        let ids = Object.keys (tickers);
        let result = {};
        for (let i = 0; i < ids.length; i++) {
            let id = ids[i];
            let market = undefined;
            let symbol = id;
            if (id in this.markets_by_id) {
                market = this.markets_by_id[id];
                symbol = market['symbol'];
            } else {
                let base = id.slice (0, 3);
                let quote = id.slice (3, 6);
                base = base.toUpperCase ();
                quote = quote.toUpperCase ();
                base = this.commonCurrencyCode (base);
                quote = this.commonCurrencyCode (quote);
                symbol = base + '/' + quote;
            }
            let ticker = tickers[id];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

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

    parseTrade (trade, market = undefined) {
        let timestamp = this.parse8601 (trade['created_at']);
        return {
            'id': trade['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': undefined,
            'price': this.safeFloat (trade, 'price'),
            'amount': this.safeFloat (trade, 'volume'),
            'cost': this.safeFloat (trade, 'funds'),
            'info': trade,
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetTrades (this.extend ({
            'market': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
        return [
            ohlcv[0] * 1000,
            ohlcv[1],
            ohlcv[2],
            ohlcv[3],
            ohlcv[4],
            ohlcv[5],
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (limit === undefined) {
            limit = 30; // default is 30
        }
        const request = {
            'market': market['id'],
            'period': this.timeframes[timeframe],
            'limit': limit,
        };
        if (since !== undefined) {
            request['timestamp'] = since;
        } else {
            request['timestamp'] = 1800000;
        }
        const response = await this.publicGetK (this.extend (request, params));
        return this.parseOHLCVs (response, market, timeframe, since, limit);
    }

    parseOrder (order, market = undefined) {
        let symbol = undefined;
        if (market !== undefined) {
            symbol = market['symbol'];
        } else {
            let marketId = order['market'];
            symbol = this.markets_by_id[marketId]['symbol'];
        }
        let timestamp = this.parse8601 (order['created_at']);
        let state = order['state'];
        let status = undefined;
        if (state === 'done') {
            status = 'closed';
        } else if (state === 'wait') {
            status = 'open';
        } else if (state === 'cancel') {
            status = 'canceled';
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': undefined,
            'status': status,
            'symbol': symbol,
            'type': order['ord_type'],
            'side': order['side'],
            'price': this.safeFloat (order, 'price'),
            'amount': this.safeFloat (order, 'volume'),
            'filled': this.safeFloat (order, 'executed_volume'),
            'remaining': this.safeFloat (order, 'remaining_volume'),
            'trades': undefined,
            'fee': undefined,
            'info': order,
        };
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let request = {
            'market': this.marketId (symbol),
            'side': side,
            'volume': amount.toString (),
            'ord_type': type,
        };
        if (type === 'limit') {
            request['price'] = price.toString ();
        }
        let response = await this.privatePostOrders (this.extend (request, params));
        let market = this.markets_by_id[response['market']];
        return this.parseOrder (response, market);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePostOrderDelete ({ 'id': id });
        let order = this.parseOrder (result);
        let status = order['status'];
        if (status === 'closed' || status === 'canceled') {
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        }
        return order;
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        let currency = this.currency (code);
        let id = this.safeString (params, 'id');
        if (id === undefined) {
            throw new ExchangeError (this.id + ' withdraw() requires an extra id param (withdraw account id according to withdraws/bind_account_list endpoint');
        }
        let request = {
            'id': id,
            'currency_type': 'coin', // or 'cash'
            'currency': currency.toLowerCase (),
            'body': amount,
            // 'address': address, // they don't allow withdrawing to direct addresses?
        };
        if (tag !== undefined) {
            request['memo'] = tag;
        }
        let result = await this.privatePostWithdrawsApply (this.extend (request, params));
        return {
            'info': result,
            'id': undefined,
        };
    }

    nonce () {
        return this.milliseconds ();
    }

    encodeParams (params) {
        return this.urlencode (this.keysort (params));
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + 'api/' + this.version + '/' + this.implodeParams (path, params) + '.json';
        let query = this.omit (params, this.extractParams (path));
        let url = this.urls['api'] + request;
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        } else {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let sortedByKey = this.keysort (this.extend ({
                'access_key': this.apiKey,
                'tonce': nonce,
            }, params));
            let query = this.urlencode (sortedByKey);
            let payload = method + '|' + request + '|' + query;
            let signature = this.hmac (this.encode (payload), this.encode (this.secret));
            let suffix = query + '&signature=' + signature;
            if (method === 'GET') {
                url += '?' + suffix;
            } else {
                body = suffix;
                headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (code, reason, url, method, headers, body, response) {
        if (code === 400) {
            const error = this.safeValue (response, 'error');
            const errorCode = this.safeString (error, 'code');
            const feedback = this.id + ' ' + this.json (response);
            const exceptions = this.exceptions;
            if (errorCode in exceptions) {
                throw new exceptions[errorCode] (feedback);
            }
            // fallback to default error handler
        }
    }
};
<|endoftext|>