<commit_before>var upload_url = "http://127.0.0.1:5000/upload"
var check_url = "http://127.0.0.1:5000/data/one/"

var store = new Store()

function changeStatus(step, text){
  text = JSON.stringify(text)
  text = step + " | " + text
  document.getElementById("load_status").innerHTML=text
}

function handleUpload(file, filename){
  var data = new FormData()
  data.append('file', file)
  data.append('filename', filename)
  changeStatus("UPLOAD", "Begun upload")
  fetch(upload_url, {
    credentials: "same-origin",
    method: "POST",
    body: data
  }).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => changeStatus("UPLOAD", success) // Handle the success response object
  ).catch(
    error => changeStatus("UPLOAD", error) // Handle the error response object
  );
}

function handleCheck(filename){
  fetch(check_url + filename, {credentials: "same-origin"}).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => changeStatus("CHECK", success) // Handle the success response object
  ).catch(
    error => changeStatus("CHECK", error) // Handle the error response object
  );
}

function handlePost(filename, slidename){
  fetch(check_url + filename, {credentials: "same-origin"}).then(
    response => response.json() // if the response is a JSON object
  ).then(
    data => {
      data.name = slidename
      data.location = "/images/" + filename
      data.mpp = data['MPP-X'] || data['MPP-Y'] || 0
      store.post("slide", {}, data).then(
        success => changeStatus("POST", success) // Handle the success response object
      ).catch(
        error => changeStatus("POST", error) // Handle the error response object
      );
    }
  ).catch(
    error => changeStatus("POST", error) // Handle the error response object
  );
}

//register events for file upload
function UploadBtn(){
  const fileInput = document.getElementById('fileinput');
  var filename = document.getElementById('filename').value
  handleUpload(fileInput.files[0], filename);
}

function CheckBtn(){
  var filename = document.getElementById('filename').value
  handleCheck(filename)
}

function PostBtn(){
  var filename = document.getElementById('filename').value
  var slidename = document.getElementById('slidename').value
  handlePost(filename, slidename)
}
<commit_msg>fufil request for date added<commit_after>var upload_url = "http://127.0.0.1:5000/upload"
var check_url = "http://127.0.0.1:5000/data/one/"

var store = new Store()

function changeStatus(step, text){
  text = JSON.stringify(text)
  text = step + " | " + text
  document.getElementById("load_status").innerHTML=text
}

function handleUpload(file, filename){
  var data = new FormData()
  data.append('file', file)
  data.append('filename', filename)
  changeStatus("UPLOAD", "Begun upload")
  fetch(upload_url, {
    credentials: "same-origin",
    method: "POST",
    body: data
  }).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => changeStatus("UPLOAD", success) // Handle the success response object
  ).catch(
    error => changeStatus("UPLOAD", error) // Handle the error response object
  );
}

function handleCheck(filename){
  fetch(check_url + filename, {credentials: "same-origin"}).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => changeStatus("CHECK", success) // Handle the success response object
  ).catch(
    error => changeStatus("CHECK", error) // Handle the error response object
  );
}

function handlePost(filename, slidename){
  fetch(check_url + filename, {credentials: "same-origin"}).then(
    response => response.json() // if the response is a JSON object
  ).then(
    data => {
      data['upload_date'] = new Date(Date.now()).toLocaleString();
      data.name = slidename
      data.location = "/images/" + filename
      data.mpp = data['MPP-X'] || data['MPP-Y'] || 0
      store.post("slide", {}, data).then(
        success => changeStatus("POST", success) // Handle the success response object
      ).catch(
        error => changeStatus("POST", error) // Handle the error response object
      );
    }
  ).catch(
    error => changeStatus("POST", error) // Handle the error response object
  );
}

//register events for file upload
function UploadBtn(){
  const fileInput = document.getElementById('fileinput');
  var filename = document.getElementById('filename').value
  handleUpload(fileInput.files[0], filename);
}

function CheckBtn(){
  var filename = document.getElementById('filename').value
  handleCheck(filename)
}

function PostBtn(){
  var filename = document.getElementById('filename').value
  var slidename = document.getElementById('slidename').value
  handlePost(filename, slidename)
}
<|endoftext|>


<commit_before>// Control variables
var eventUpcoming = true;
var eventName = "Geburtstag"

//Mobile
navOpen = false;
function RevealNav() {
  if (navOpen == true) {
    $("#mobileOptions").css("display", "none");
    navOpen = false;
  }
  else {
    $("#mobileOptions").css("display", "block");
    navOpen = true;
  }
}

//Events
if (eventUpcoming == true) {
  $(".currentEvent").html(eventName);
  $(".currentEvent").css("display", "block");
}
else {
  $(".currentEvent").css("display", "none");
}
<commit_msg>hid event<commit_after>// Control variables
var eventUpcoming = false;
var eventName = "Geburtstag"

//Mobile
navOpen = false;
function RevealNav() {
  if (navOpen == true) {
    $("#mobileOptions").css("display", "none");
    navOpen = false;
  }
  else {
    $("#mobileOptions").css("display", "block");
    navOpen = true;
  }
}

//Events
if (eventUpcoming == true) {
  $(".currentEvent").html(eventName);
  $(".currentEvent").css("display", "block");
}
else {
  $(".currentEvent").css("display", "none");
}
<|endoftext|>


<commit_before>var Office = {
  debug: 1,
  debugStatus: {enabled: 0, data: 'bun\nBoller på kontoret!'},

  // Light limit, 0-860 is ON, 860-1023 is OFF
  lightLimit: 860,
  // Basic
  titles: {
    'error': 'Oops',
    'open': 'Åpent',
    'closed': 'Lukket',
    'meeting': 'Møte',
  },
  // Foods
  foods: {
    'waffle': {title: 'Vafler', icon: './img/icon-waffle.png'},
    'cake': {title: 'Kake', icon: './img/icon-cake.png'},
    'bun': {title: 'Boller', icon: './img/icon-bun.png'},
  },
  // Messages
  msgError: 'Klarte ikke hente kontorstatus',
  msgOpen: 'Gratis kaffe og te til alle!',
  msgClosed: 'Finn et komitemedlem for å åpne opp.',
  msgUntitledMeeting: 'Kontoret er opptatt', // titled events get names from calendar entries

  get: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var self = this;
    this.getEventData( function(status, title, message) {

      // If no events are active we'll have to check the lights as well
      if (status == 'open') {
        self.getLightData(callback);
      }
      else {
        // status: "closed"
        // title: "Lukket"
        // message: "Finn et komitemedlem for å åpne opp"
        if (self.debug) console.log('Office:\n- status is', status, '\n- title is', title, '\n- message is', message);
        callback(status, title, message);
      }
    });
  },

  getEventData: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var eventApi = Affiliation.org[localStorage.affiliationKey1].eventApi;

    // Receives info on current event from Onlines servers (without comments)
    // meeting        // current status
    // Møte: dotKom   // event title or 'No title'-meeting or nothing
    var self = this;
    Ajaxer.getPlainText({
      url: eventApi,
      success: function(data) {

        // Debug particular status?
        if (self.debug && self.debugStatus.enabled) {
          data = self.debugStatus.data;
        }

        var status = data.split('\n',2)[0]; // 'meeting'
        var title = data.split('\n',2)[1]; // 'Møte: arrKom'

        // empty meeting title?
        if (status == 'meeting' && title == '')
          title = self.msgUntitledMeeting;

        // set the status from fetched data
        switch(status) {

          case 'error': callback('error', self.titles.error, self.msgError); break;

          case 'open': callback('open', self.titles.open, self.msgOpen); break;
          case 'meeting': callback('meeting', self.titles.meeting, title); break;

          case 'waffle': callback('waffle', self.foods.waffle.title, title); break;
          case 'cake': callback('cake', self.foods.cake.title, title); break;
          case 'bun': callback('bun', self.foods.bun.title, title); break;

          default: callback('error', self.titles.error, self.msgError);
        }
      },
      error: function(jqXHR, text, err) {
        if (self.debug) console.log('ERROR: Failed to get event data.');
        callback('error', self.titles.error, self.msgError);
      },
    });
  },

  getLightData: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var lightApi = Affiliation.org[localStorage.affiliationKey1].lightApi;

    // Receives current light intensity from the office: OFF 0-800-1023 ON
    var self = this;
    Ajaxer.getPlainText({
      url: lightApi,
      success: function(data) {
        if (data > self.lightLimit) {
          callback('closed', self.titles.closed, self.msgClosed);
        }
        else {
          callback('open', self.titles.open, self.msgOpen);
        }
      },
      error: function(jqXHR, err) {
        if (self.debug) console.log('ERROR: Failed to get light data.');
        callback('error', self.titles.error, self.msgError);
      },
    });
  },

}
<commit_msg>office: changed calendar reporting from 'open' to 'free' - it's more correct since we have yet to find out whether it's open or closed<commit_after>var Office = {
  debug: 1,
  debugStatus: {enabled: 0, data: 'bun\nBoller på kontoret!'},

  // Light limit, 0-860 is ON, 860-1023 is OFF
  lightLimit: 860,
  // Basic
  titles: {
    'error': 'Oops',
    'open': 'Åpent',
    'closed': 'Lukket',
    'meeting': 'Møte',
  },
  // Foods
  foods: {
    'waffle': {title: 'Vafler', icon: './img/icon-waffle.png'},
    'cake': {title: 'Kake', icon: './img/icon-cake.png'},
    'bun': {title: 'Boller', icon: './img/icon-bun.png'},
  },
  // Messages
  msgError: 'Klarte ikke hente kontorstatus',
  msgOpen: 'Gratis kaffe og te til alle!',
  msgClosed: 'Finn et komitemedlem for å åpne opp.',
  msgUntitledMeeting: 'Kontoret er opptatt', // titled events get names from calendar entries

  get: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var self = this;
    this.getEventData( function(status, title, message) {

      // If no events are active we'll have to check the lights as well
      if (status == 'free') {
        self.getLightData(callback);
      }
      else {
        // status: "closed"
        // title: "Lukket"
        // message: "Finn et komitemedlem for å åpne opp"
        if (self.debug) console.log('Office:\n- status is', status, '\n- title is', title, '\n- message is', message);
        callback(status, title, message);
      }
    });
  },

  getEventData: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var eventApi = Affiliation.org[localStorage.affiliationKey1].eventApi;

    // Receives info on current event from Onlines servers (without comments)
    // meeting        // current status
    // Møte: dotKom   // event title or 'No title'-meeting or nothing
    var self = this;
    Ajaxer.getPlainText({
      url: eventApi,
      success: function(data) {

        // Debug particular status?
        if (self.debug && self.debugStatus.enabled) {
          data = self.debugStatus.data;
        }

        var status = data.split('\n',2)[0]; // 'meeting'
        var title = data.split('\n',2)[1]; // 'Møte: arrKom'

        // empty meeting title?
        if (status == 'meeting' && title == '')
          title = self.msgUntitledMeeting;

        // set the status from fetched data
        switch(status) {

          case 'free': callback('free'); break;

          case 'meeting': callback('meeting', self.titles.meeting, title); break;
          case 'waffle': callback('waffle', self.foods.waffle.title, title); break;
          case 'cake': callback('cake', self.foods.cake.title, title); break;
          case 'bun': callback('bun', self.foods.bun.title, title); break;

          case 'error':
          default: callback('error', self.titles.error, self.msgError);
        }
      },
      error: function(jqXHR, text, err) {
        if (self.debug) console.log('ERROR: Failed to get event data.');
        callback('error', self.titles.error, self.msgError);
      },
    });
  },

  getLightData: function(callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }

    var lightApi = Affiliation.org[localStorage.affiliationKey1].lightApi;

    // Receives current light intensity from the office: OFF 0-800-1023 ON
    var self = this;
    Ajaxer.getPlainText({
      url: lightApi,
      success: function(data) {
        if (data > self.lightLimit) {
          if (self.debug) console.log('Office:\n- status is', status, '\n- title is', self.titles.closed, '\n- message is', self.msgClosed);
          callback('closed', self.titles.closed, self.msgClosed);
        }
        else {
          if (self.debug) console.log('Office:\n- status is', status, '\n- title is', self.titles.open, '\n- message is', self.msgOpen);
          callback('open', self.titles.open, self.msgOpen);
        }
      },
      error: function(jqXHR, err) {
        if (self.debug) console.log('ERROR: Failed to get light data.');
        callback('error', self.titles.error, self.msgError);
      },
    });
  },

}
<|endoftext|>


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

var expect = require('chai').expect;

var taskList = [ ];

// I can list my tasks...
function listTasks(){
}

// I can add a task to my list...
function addTaskToList(task, list){
  // What is the task? @param task
  // Where is the task going? @param list
  // What order / priority? lowest, on the bottom
  return list.push(task);
  // add task to list somehow on the bottom
}
expect(taskList.length).to.equal[0];
addTaskToList("Remember the milk", taskList);
expect(TaskToList[0]).to.equal("Remember the milk");
expect(TaskToList.length).to.equal(1);

// expect what?
expect(taskList.length).to.equal[1]
addTaskToList("Take out the trash", tasklist[1]);

// expect what now?
<commit_msg>Input corrections<commit_after>// var chai = require('chai')
//    expect = chai.expect;

var expect = require('chai').expect;

var taskList = [ ];

// I can list my tasks...
function listTasks(){
}

// I can add a task to my list...
function addTaskToList(task, list){
  // What is the task? @param task
  // Where is the task going? @param list
  // What order / priority? lowest, on the bottom
  return list.push(task);
  // add task to list somehow on the bottom
}
expect(taskList.length).to.equal[0];
addTaskToList("Remember the milk", taskList);
expect(tasklist[0]).to.equal("Remember the milk");
expect(tasklist.length).to.equal(1);

// expect what?
expect(taskList.length).to.equal[1]
addTaskToList("Take out the trash", tasklist[1]);

// expect what now?
<|endoftext|>


<commit_before>var Oracle = {
  debug: 0,
  api: 'http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=',
  msgAboutPredict: 'Etter å ha brukt orakelet en stund kan det forutsi spørsmålet ditt når du trykker [tab]',
  msgDisconnected: 'Frakoblet fra m.atb.no',
  msgSuggestPredict: 'Trykk [tab] for å spørre om: ',

  __loadDefaults: function() {
    if (localStorage.oracleBrain == undefined) {
      var oracleBrain = {};
      for (var i=0; i<=6; i++)
        oracleBrain[i] = {night:'', morning:'', afternoon:'', evening:''};
      localStorage.oracleBrain = JSON.stringify(oracleBrain);
    }
  }(),

  ask: function(question, callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }
    if (isEmpty(question)) {
      console.log('ERROR: question is empty');
      return;
    }

    // Encode URL component.... as it says below :D
    var encodedQuestion = encodeURIComponent(question);

    var self = this;
    Ajaxer.getPlainText({
      url: self.api + encodedQuestion,
      success: function(answer) {
        answer = self.shorten(answer);

        // Store answer for later prediction
        self.consider(question, answer);

        // Call it back
        callback(answer);
      },
      error: function(jqXHR, text, err) {
        callback(self.msgDisconnected);
      },
    });
  },

  greet: function() {
    var greetings = [
      // Spørsmål
      'Når vil du ta bussen?',
      'Bussorakelet trenger noe å gjøre, har du et spørsmål?',
      'Har du et busspørsmål eller skal du bare lese litt tilfeldig tekst?',
      'Lurer du på hvilken buss du skal ta?',
      'Vil du ta bussen til Samfundet kanskje?',
      'Vil du ta bussen til kjellerne på Moholt kanskje?',
      'Har du et lite bussspørsmål?',
      'Skal det være en buss?',
      'Vil du ha en liten privat buss kanskje? En femseter?',

      // Statements
      'Orakelet tar gjerne imot spørsmål.',
      'Orakelet vet alt om hvilke busser som kjører.',
      'Orakelet svarer på alle spørsmål om busser.',
      'Spør, og du vil få svar.',
      'Bussorakelet er sultent på spørsmål, eller kantinemat, alt ettersom.',
      'Spør et busspørsmål her.',
      'De som laget Notifier er ganske snille mot AtB.',
      'Ta bussen til Tiller og kjøp no stæsj du trenger.',
      'Ta bussen til Nidar og spis masse sjokolade.',
      'Ta bussen til campus når det er for kaldt for å sykle.',
      'Tralala, jeg kan synge en sang.',
      'Buss her, buss der, buss overalt.',

      // Funfacts
      'Bussorakelet ble utviklet på NTNU, spør om noe!',
      'Tri M. Nguyen har laget APIet som brukes til sanntiden. Takk, Tri <3',
      'Tri M. Nguyen har laget APIet som Notifier bruker, det er på api.visuweb.no/bybussen',
      'AtB har minibusser også.',
      'UKA har en egen buss.',
      'Flybussen går hvert 10. minutt.',
      'Leddbusser har wifi.',
      'AtB har også langdistansebusser, de er mørkegrønne.',
      'Da Roy Sindre fant nøkkelen ble det plutselig en bussapp før AtB visste hva som skjedde.',
      'En av bussjåførene er julenisse hver desember.',
      'Både AtB og SiT liker Notifier.',
      'Notifier fikk støtte for sanntidsbuss i versjon 1.3.0.',
      'Notifier og bussorakelet ble venner i Notifier versjon 1.3.1',
      'Tenk om Kantinelizzie hadde kjørt buss.',
      'Hvis du har installert Notifier på forskjellige maskiner kan du ha forskjellige busstopp på hver.',
      'Større busser, flere busser, raskere busser, AtB gjør alle tre på 5ern.',
      'En gang gikk 5ern via Gryta og Lohove til Dragvoll.',
      'Før i tiden møttes alle bussene i Munkegata/Dronningens gate.',
      'AtB laget egen bussapp som het Bussøyet, men den var for sent etter Bartebuss.',
      'Det finnes mange bussapper.',
      'AtB sitt API er laget av italienere.',
      'AtB sitt API har italienske metodenavn.',
      'Bartebuss og ByBussen er de beste bussappene.',
      'Bussene sjekker inn med GPS på hvert stopp, cirka.',
      'Bussene som må kjøre langt mellom hvert stopp har upresis sanntid.',
      'busskartet.no er ganske morsomt.',
      'Han som laget busskartet.no må ha kost seg gløgg i hjæl med alle de små bussene sine.',
      'Sekkemannen sitter alltid på en utgave av Under Dusken for å unngå bakterier fra bussetet.',

      // Om orakelet
      'Bussorakelets wiki er på ntnu.no/wiki/display/FUIROS',
      'Bussorakelet kom til live i 1998.',
      'I 2002 begynte bussorakelet å besvare spørsmål på SMS.',
      'BussTUC betyr "Buss: The Understanding Computer".',
      'Orakelet består av tre hjerner: Den første kan beregning, den andre kan språk, den tredje forstår de to første.',
      'Orakelet forstår språk ved hjelp av et komplekst sett med regler skrevet i Prolog.',
      'Bussorakelet er den sentrale delen i FUIROS-prosjektet.',
      'Orakelet kan 4590 ord, 1204 stoppnavn, 80 busslinjer og 9970 navnevarianter.',
      'Orakelet forstår språk ved hjelp av 5000 språkregler.',
      'Orakelet kan 960 substantiv, 1100 verb og 450 adjektiv.',
      'Orakelets kodebase består av 130.500 linjer Prolog.',
      'Orakelet forstår språk ved hjelp av "Consensical Grammar" (CONtext SENSItive CompositionAL Grammar).',

      // Team Trafikk
      'AtB er tusen ganger bedre enn Team Trafikk var.',
      'I 2010 byttet Team Trafikk navn til AtB, og byttet eiere.',
      'Team Trafikk sine busser var hvite, gamle og slitne.',
      'Da Team Trafikk ble AtB ble alt mye bedre.',
      'Da Team Trafikk ble AtB fikk de miljøvennlige busser.',
      'Da Team Trafikk ble AtB fikk de grønnere busser.',
      'Da Team Trafikk ble AtB fikk de mobillett.',
      'Da Team Trafikk ble AtB fikk de nye kontorer.',
      'Da Team Trafikk ble AtB fikk de API-er som man kunne hente data fra.',
      'Da Team Trafikk ble AtB fant Roy Sindre en nøkkel til API-et, han spurte ikke om lov.',
      'Åpne bussdata var veldig lurt av AtB.',

      // Contributors
      'Christoffer J. Marcussen er en av hjernene bak bussorakelet (2011-2012).',
      'Jon S. Bratseth er en av hjernene bak bussorakelet (1996-1997).',
      'Magnus Raaum er en av hjernene bak bussorakelet (2010-2011).',
      'Martin T. Ranang er en av hjernene bak bussorakelet (2001-2011).',
      'Marius Q. Wollamo er en av hjernene bak bussorakelet (2012-2013).',
      'Runar Andersstuen er en av hjernene bak bussorakelet (2011-2012).',
      'Rune M. Andersen er en av hjernene bak bussorakelet (2011-2012).',
      'Rune Sætre er en av hjernene bak bussorakelet (2000-2012).',
      'Tore Amble er en av hjernene bak bussorakelet (1996-2012).',
      'Tore Bruland er en av hjernene bak bussorakelet (2004-2011).',
      'Trond Bø Engell er en av hjernene bak bussorakelet (2011-2012).',
    ];
    var randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
    return randomGreeting;
  },

  predict: function() {
    var oracleBrain = JSON.parse(localStorage.oracleBrain);

    // Get question from timeslot
    var timeslot = this.getTimeslot();
    var question = oracleBrain[timeslot.day][timeslot.hour];
    if (this.debug) console.log('Oracle predicting question for day '+timeslot.day+' in the '+timeslot.hour+': "'+question+'"');

    return (question != '' ? question : null);
  },

  // Private functions, do not use externally

  consider: function(question, answer) {
    if (this.debug) console.log('Oracle considering...\n- Question:', question, '\n- Answer:', answer);

    var pieces = answer.match(/buss|til|fra|passerer|kommer|senere/gi);
    if (pieces != null) {
      if (pieces.length >= 3) {
        var oracleBrain = JSON.parse(localStorage.oracleBrain);

        // Get timeslot
        var timeslot = this.getTimeslot();

        // Insert question at correct timeslot
        oracleBrain[timeslot.day][timeslot.hour] = question;
        if (this.debug) console.log('Oracle considered question to be valuable');

        // Stringify the brain
        localStorage.oracleBrain = JSON.stringify(oracleBrain);
      }
      else {
        if (this.debug) console.log('Oracle thinks the answer did not contain enough expected keywords');
      }
    }
    else {
      if (this.debug) console.log('Oracle thinks the answer did not contain expected keywords');
    }
  },

  getTimeslot: function() {
    // Night:       0 -  5:59
    // Morning:     6 - 11:59
    // Afternoon:  12 - 17:59
    // Evening:    18 - 23:59
    var d = new Date();
    var hour = d.getHours();

    var timeslot = {};
    timeslot.day = d.getDay();

    if (0 <= hour && hour < 6)
      timeslot.hour = 'night';
    else if (6 <= hour && hour < 12)
      timeslot.hour = 'morning';
    else if (12 <= hour && hour < 18)
      timeslot.hour = 'afternoon';
    else //if (18 <= hour && hour <= 23)
      timeslot.hour = 'evening';

    return timeslot;
  },

  shorten: function(answer) {
    // Example:
    // "Holdeplassen nærmest Gløshaugen er Gløshaugen Syd. Buss 5 går fra
    // Gløshaugen Syd kl. 2054 til Prinsen kinosenter kl. 2058 og buss 19
    // går fra Prinsen kinosenter kl. 2105 til Studentersamfundet kl. 2106.
    // Tidene angir tidligste passeringer av holdeplassene."
    var pieces = answer.split('. ');
    // Slice away "Holdeplassen nærmest X er X."
    if (pieces[0].startsWith('Holdeplassen nærmest')) {
      pieces = pieces.slice(1);
    }
    // Slice away "Tidene angir tidligste passeringer av holdeplassene."
    if (pieces[pieces.length-1].startsWith('Tidene angir tidligste')) {
      pieces = pieces.slice(0, pieces.length-1);
    }
    return pieces.join('. ') + '.';
  },

}
<commit_msg>oracle: removing Bartebuss from greetings cuz it appears to use outdated info<commit_after>var Oracle = {
  debug: 0,
  api: 'http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=',
  msgAboutPredict: 'Etter å ha brukt orakelet en stund kan det forutsi spørsmålet ditt når du trykker [tab]',
  msgDisconnected: 'Frakoblet fra m.atb.no',
  msgSuggestPredict: 'Trykk [tab] for å spørre om: ',

  __loadDefaults: function() {
    if (localStorage.oracleBrain == undefined) {
      var oracleBrain = {};
      for (var i=0; i<=6; i++)
        oracleBrain[i] = {night:'', morning:'', afternoon:'', evening:''};
      localStorage.oracleBrain = JSON.stringify(oracleBrain);
    }
  }(),

  ask: function(question, callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }
    if (isEmpty(question)) {
      console.log('ERROR: question is empty');
      return;
    }

    // Encode URL component.... as it says below :D
    var encodedQuestion = encodeURIComponent(question);

    var self = this;
    Ajaxer.getPlainText({
      url: self.api + encodedQuestion,
      success: function(answer) {
        answer = self.shorten(answer);

        // Store answer for later prediction
        self.consider(question, answer);

        // Call it back
        callback(answer);
      },
      error: function(jqXHR, text, err) {
        callback(self.msgDisconnected);
      },
    });
  },

  greet: function() {
    var greetings = [
      // Spørsmål
      'Når vil du ta bussen?',
      'Bussorakelet trenger noe å gjøre, har du et spørsmål?',
      'Har du et busspørsmål eller skal du bare lese litt tilfeldig tekst?',
      'Lurer du på hvilken buss du skal ta?',
      'Vil du ta bussen til Samfundet kanskje?',
      'Vil du ta bussen til kjellerne på Moholt kanskje?',
      'Har du et lite bussspørsmål?',
      'Skal det være en buss?',
      'Vil du ha en liten privat buss kanskje? En femseter?',

      // Statements
      'Orakelet tar gjerne imot spørsmål.',
      'Orakelet vet alt om hvilke busser som kjører.',
      'Orakelet svarer på alle spørsmål om busser.',
      'Spør, og du vil få svar.',
      'Bussorakelet er sultent på spørsmål, eller kantinemat, alt ettersom.',
      'Spør et busspørsmål her.',
      'De som laget Notifier er ganske snille mot AtB.',
      'Ta bussen til Tiller og kjøp no stæsj du trenger.',
      'Ta bussen til Nidar og spis masse sjokolade.',
      'Ta bussen til campus når det er for kaldt for å sykle.',
      'Tralala, jeg kan synge en sang.',
      'Buss her, buss der, buss overalt.',

      // Funfacts
      'Bussorakelet ble utviklet på NTNU, spør om noe!',
      'Tri M. Nguyen har laget APIet som brukes til sanntiden. Takk, Tri <3',
      'Tri M. Nguyen har laget APIet som Notifier bruker, det er på api.visuweb.no/bybussen',
      'AtB har minibusser også.',
      'UKA har en egen buss.',
      'Flybussen går hvert 10. minutt.',
      'Leddbusser har wifi.',
      'AtB har også langdistansebusser, de er mørkegrønne.',
      'Da Roy Sindre fant nøkkelen ble det plutselig en bussapp før AtB visste hva som skjedde.',
      'En av bussjåførene er julenisse hver desember.',
      'Både AtB og SiT liker Notifier.',
      'Notifier fikk støtte for sanntidsbuss i versjon 1.3.0.',
      'Notifier og bussorakelet ble venner i Notifier versjon 1.3.1',
      'Tenk om Kantinelizzie hadde kjørt buss.',
      'Hvis du har installert Notifier på forskjellige maskiner kan du ha forskjellige busstopp på hver.',
      'Større busser, flere busser, raskere busser, AtB gjør alle tre på 5ern.',
      'En gang gikk 5ern via Gryta og Lohove til Dragvoll.',
      'Før i tiden møttes alle bussene i Munkegata/Dronningens gate.',
      'AtB laget egen bussapp som het Bussøyet, men den var for sent etter 5 studentlagde apper.',
      'Det finnes mange bussapper.',
      'AtB sitt API er laget av italienere.',
      'AtB sitt API har italienske metodenavn.',
      'ByBussen er den mest oppdaterte bussappen.',
      'Bussene sjekker inn med GPS på hvert stopp, cirka.',
      'Bussene som må kjøre langt mellom hvert stopp har upresis sanntid.',
      'busskartet.no er ganske morsomt.',
      'Han som laget busskartet.no må ha kost seg gløgg i hjæl med alle de små bussene sine.',
      'Sekkemannen sitter alltid på en utgave av Under Dusken for å unngå bakterier fra bussetet.',

      // Om orakelet
      'Bussorakelets wiki er på ntnu.no/wiki/display/FUIROS',
      'Bussorakelet kom til live i 1998.',
      'I 2002 begynte bussorakelet å besvare spørsmål på SMS.',
      'BussTUC betyr "Buss: The Understanding Computer".',
      'Orakelet består av tre hjerner: Den første kan beregning, den andre kan språk, den tredje forstår de to første.',
      'Orakelet forstår språk ved hjelp av et komplekst sett med regler skrevet i Prolog.',
      'Bussorakelet er den sentrale delen i FUIROS-prosjektet.',
      'Orakelet kan 4590 ord, 1204 stoppnavn, 80 busslinjer og 9970 navnevarianter.',
      'Orakelet forstår språk ved hjelp av 5000 språkregler.',
      'Orakelet kan 960 substantiv, 1100 verb og 450 adjektiv.',
      'Orakelets kodebase består av 130.500 linjer Prolog.',
      'Orakelet forstår språk ved hjelp av "Consensical Grammar" (CONtext SENSItive CompositionAL Grammar).',

      // Team Trafikk
      'AtB er tusen ganger bedre enn Team Trafikk var.',
      'I 2010 byttet Team Trafikk navn til AtB, og byttet eiere.',
      'Team Trafikk sine busser var hvite, gamle og slitne.',
      'Da Team Trafikk ble AtB ble alt mye bedre.',
      'Da Team Trafikk ble AtB fikk de miljøvennlige busser.',
      'Da Team Trafikk ble AtB fikk de grønnere busser.',
      'Da Team Trafikk ble AtB fikk de mobillett.',
      'Da Team Trafikk ble AtB fikk de nye kontorer.',
      'Da Team Trafikk ble AtB fikk de API-er som man kunne hente data fra.',
      'Da Team Trafikk ble AtB fant Roy Sindre en nøkkel til API-et, han spurte ikke om lov.',
      'Åpne bussdata var veldig lurt av AtB.',

      // Contributors
      'Christoffer J. Marcussen er en av hjernene bak bussorakelet (2011-2012).',
      'Jon S. Bratseth er en av hjernene bak bussorakelet (1996-1997).',
      'Magnus Raaum er en av hjernene bak bussorakelet (2010-2011).',
      'Martin T. Ranang er en av hjernene bak bussorakelet (2001-2011).',
      'Marius Q. Wollamo er en av hjernene bak bussorakelet (2012-2013).',
      'Runar Andersstuen er en av hjernene bak bussorakelet (2011-2012).',
      'Rune M. Andersen er en av hjernene bak bussorakelet (2011-2012).',
      'Rune Sætre er en av hjernene bak bussorakelet (2000-2012).',
      'Tore Amble er en av hjernene bak bussorakelet (1996-2012).',
      'Tore Bruland er en av hjernene bak bussorakelet (2004-2011).',
      'Trond Bø Engell er en av hjernene bak bussorakelet (2011-2012).',
    ];
    var randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
    return randomGreeting;
  },

  predict: function() {
    var oracleBrain = JSON.parse(localStorage.oracleBrain);

    // Get question from timeslot
    var timeslot = this.getTimeslot();
    var question = oracleBrain[timeslot.day][timeslot.hour];
    if (this.debug) console.log('Oracle predicting question for day '+timeslot.day+' in the '+timeslot.hour+': "'+question+'"');

    return (question != '' ? question : null);
  },

  // Private functions, do not use externally

  consider: function(question, answer) {
    if (this.debug) console.log('Oracle considering...\n- Question:', question, '\n- Answer:', answer);

    var pieces = answer.match(/buss|til|fra|passerer|kommer|senere/gi);
    if (pieces != null) {
      if (pieces.length >= 3) {
        var oracleBrain = JSON.parse(localStorage.oracleBrain);

        // Get timeslot
        var timeslot = this.getTimeslot();

        // Insert question at correct timeslot
        oracleBrain[timeslot.day][timeslot.hour] = question;
        if (this.debug) console.log('Oracle considered question to be valuable');

        // Stringify the brain
        localStorage.oracleBrain = JSON.stringify(oracleBrain);
      }
      else {
        if (this.debug) console.log('Oracle thinks the answer did not contain enough expected keywords');
      }
    }
    else {
      if (this.debug) console.log('Oracle thinks the answer did not contain expected keywords');
    }
  },

  getTimeslot: function() {
    // Night:       0 -  5:59
    // Morning:     6 - 11:59
    // Afternoon:  12 - 17:59
    // Evening:    18 - 23:59
    var d = new Date();
    var hour = d.getHours();

    var timeslot = {};
    timeslot.day = d.getDay();

    if (0 <= hour && hour < 6)
      timeslot.hour = 'night';
    else if (6 <= hour && hour < 12)
      timeslot.hour = 'morning';
    else if (12 <= hour && hour < 18)
      timeslot.hour = 'afternoon';
    else //if (18 <= hour && hour <= 23)
      timeslot.hour = 'evening';

    return timeslot;
  },

  shorten: function(answer) {
    // Example:
    // "Holdeplassen nærmest Gløshaugen er Gløshaugen Syd. Buss 5 går fra
    // Gløshaugen Syd kl. 2054 til Prinsen kinosenter kl. 2058 og buss 19
    // går fra Prinsen kinosenter kl. 2105 til Studentersamfundet kl. 2106.
    // Tidene angir tidligste passeringer av holdeplassene."
    var pieces = answer.split('. ');
    // Slice away "Holdeplassen nærmest X er X."
    if (pieces[0].startsWith('Holdeplassen nærmest')) {
      pieces = pieces.slice(1);
    }
    // Slice away "Tidene angir tidligste passeringer av holdeplassene."
    if (pieces[pieces.length-1].startsWith('Tidene angir tidligste')) {
      pieces = pieces.slice(0, pieces.length-1);
    }
    return pieces.join('. ') + '.';
  },

}
<|endoftext|>


<commit_before>var Oracle = {
  api: 'http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=',
  msgDisconnected: 'Frakoblet fra m.atb.no',

  get: function(question, callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }
    if (isEmpty(question)) {
      console.log('ERROR: question is empty');
      return;
    }

    // Encode URL component.... as it says below :D
    question = encodeURIComponent(question);

    var self = this;
    Ajaxer.getPlainText({
      url: self.api + question,
      success: function(answer) {
        answer = self.shorten(answer);
        callback(answer);
      },
      error: function(jqXHR, text, err) {
        callback(self.msgDisconnected);
      },
    });
  },

  greet: function() {
    var greetings = [
      // Spørsmål
      'Når vil du ta bussen?',
      'Bussorakelet trenger noe å gjøre, har du et spørsmål?',
      'Har du et busspørsmål eller skal du bare lese litt tilfeldig tekst?',
      'Lurer du på hvilken buss du skal ta?',
      'Vil du ta bussen til Samfundet kanskje?',
      'Vil du ta bussen til kjellerne på Moholt kanskje?',
      'Har du et lite bussspørsmål?',
      'Skal det være en buss?',
      'Vil du ha en liten privat buss kanskje? En femseter?',

      // Statements
      'Orakelet tar gjerne imot spørsmål.',
      'Orakelet vet alt om hvilke busser som kjører.',
      'Orakelet svarer på alle spørsmål om busser.',
      'Spør, og du vil få svar.',
      'Bussorakelet er sultent på spørsmål, eller kantinemat, alt ettersom.',
      'Spør et busspørsmål her!',
      'De som laget Notifier er ganske snille mot AtB.',
      'Ta bussen til Tiller og kjøp no stæsj du trenger.',
      'Ta bussen til Nidar og spis masse sjokolade.',
      'Tralala, jeg kan synge en sang.',
      'Buss her, buss der, buss overalt.',
      'Ta bussen til campus.',

      // Funfacts
      'Bussorakelet ble utviklet på NTNU, spør om noe!',
      'Tri M. Nguyen har laget APIet som brukes til sanntiden.',
      'AtB har minibusser også.',
      'UKA har en egen buss.',
      'Flybussen går hvert 10. minutt.',
      'Leddbusser har wifi.',
      'AtB har også langdistansebusser, de er mørkegrønne.',
      'Da Roy Sindre fant nøkkelen ble det plutselig en bussapp før AtB visste hva som skjedde.',
      'En av bussjåførene er julenisse hver desember.',
      'Både AtB og SiT liker Notifier.',
      'Notifier fikk støtte for sanntidsbuss i versjon 1.3.0.',
      'Tenk om Kantinelizzie hadde kjørt buss.',
      'Hvis du har installert Notifier på forskjellige maskiner kan du ha forskjellige busstopp på hver.',
      'Større busser, flere busser, raskere busser, AtB gjør alle tre på 5ern.',
      'En gang gikk 5ern via Gryta og Lohove til Dragvoll.',
      'Før i tiden møttes alle bussene i Munkegata/Dronningens gate.',
      'AtB laget egen bussapp som het Bussøyet, men den var for sent etter Bartebuss.',
      'Det finnes mange bussapper.',
      'Bartebuss og ByBussen er de beste bussappene.',
      'AtB sitt API er laget av italienere.',
      'AtB sitt API har italienske metodenavn.',
      'Bussene sjekker inn med GPS på hvert stopp, cirka.',
      'Bussene som må kjøre langt mellom hvert stopp har upresis sanntid.',
      'busskartet.no er ganske morsomt.',
      'Han som laget busskartet.no må ha kost seg gløgg i hjæl med alle de små bussene sine.',

      // Team Trafikk
      'AtB er tusen ganger bedre enn Team Trafikk var.',
      'I 2010 byttet Team Trafikk navn til AtB, og byttet eiere.',
      'Team Trafikk sine busser var hvite, gamle og slitne.',
      'Da Team Trafikk ble AtB ble alt mye bedre.',
      'Da Team Trafikk ble AtB fikk de miljøvennlige busser.',
      'Da Team Trafikk ble AtB fikk de grønnere busser.',
      'Da Team Trafikk ble AtB fikk de mobillett.',
      'Da Team Trafikk ble AtB fikk de nye kontorer.',
      'Da Team Trafikk ble AtB fikk de API-er som man kunne hente data fra.',
      'Da Team Trafikk ble AtB fant Roy Sindre en nøkkel til API-et, han spurte ikke om lov.',
      'Åpne bussdata var veldig lurt av AtB.',
    ];
    var randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
    return randomGreeting;
  },

  // Private functions, do not use externally

  shorten: function(answer) {

    // Example:
    // "Holdeplassen nærmest Gløshaugen er Gløshaugen Syd. Buss 5 går fra
    // Gløshaugen Syd kl. 2054 til Prinsen kinosenter kl. 2058 og buss 19
    // går fra Prinsen kinosenter kl. 2105 til Studentersamfundet kl. 2106.
    // Tidene angir tidligste passeringer av holdeplassene."

    var pieces = answer.split('. ');

    // Slice away "Holdeplassen nærmest X er X."
    if (pieces[0].startsWith('Holdeplassen nærmest')) {
      pieces = pieces.slice(1);
    }

    // Slice away "Tidene angir tidligste passeringer av holdeplassene."
    if (pieces[pieces.length-1].startsWith('Tidene angir tidligste')) {
      pieces = pieces.slice(0, pieces.length-1);
    }

    return pieces.join('. ') + '.';
  },

}
<commit_msg>oracle: more greetings<commit_after>var Oracle = {
  api: 'http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=',
  msgDisconnected: 'Frakoblet fra m.atb.no',

  get: function(question, callback) {
    if (callback == undefined) {
      console.log('ERROR: Callback is required. In the callback you should insert the results into the DOM.');
      return;
    }
    if (isEmpty(question)) {
      console.log('ERROR: question is empty');
      return;
    }

    // Encode URL component.... as it says below :D
    question = encodeURIComponent(question);

    var self = this;
    Ajaxer.getPlainText({
      url: self.api + question,
      success: function(answer) {
        answer = self.shorten(answer);
        callback(answer);
      },
      error: function(jqXHR, text, err) {
        callback(self.msgDisconnected);
      },
    });
  },

  greet: function() {
    var greetings = [
      // Spørsmål
      'Når vil du ta bussen?',
      'Bussorakelet trenger noe å gjøre, har du et spørsmål?',
      'Har du et busspørsmål eller skal du bare lese litt tilfeldig tekst?',
      'Lurer du på hvilken buss du skal ta?',
      'Vil du ta bussen til Samfundet kanskje?',
      'Vil du ta bussen til kjellerne på Moholt kanskje?',
      'Har du et lite bussspørsmål?',
      'Skal det være en buss?',
      'Vil du ha en liten privat buss kanskje? En femseter?',

      // Statements
      'Orakelet tar gjerne imot spørsmål.',
      'Orakelet vet alt om hvilke busser som kjører.',
      'Orakelet svarer på alle spørsmål om busser.',
      'Spør, og du vil få svar.',
      'Bussorakelet er sultent på spørsmål, eller kantinemat, alt ettersom.',
      'Spør et busspørsmål her!',
      'De som laget Notifier er ganske snille mot AtB.',
      'Ta bussen til Tiller og kjøp no stæsj du trenger.',
      'Ta bussen til Nidar og spis masse sjokolade.',
      'Tralala, jeg kan synge en sang.',
      'Buss her, buss der, buss overalt.',
      'Ta bussen til campus.',

      // Funfacts
      'Bussorakelet ble utviklet på NTNU, spør om noe!',
      'Tri M. Nguyen har laget APIet som brukes til sanntiden. Tri <3',
      'AtB har minibusser også.',
      'UKA har en egen buss.',
      'Flybussen går hvert 10. minutt.',
      'Leddbusser har wifi.',
      'AtB har også langdistansebusser, de er mørkegrønne.',
      'Da Roy Sindre fant nøkkelen ble det plutselig en bussapp før AtB visste hva som skjedde.',
      'En av bussjåførene er julenisse hver desember.',
      'Både AtB og SiT liker Notifier.',
      'Notifier fikk støtte for sanntidsbuss i versjon 1.3.0.',
      'Notifier og bussorakelet ble venner i Notifier versjon 1.3.1',
      'Tenk om Kantinelizzie hadde kjørt buss.',
      'Hvis du har installert Notifier på forskjellige maskiner kan du ha forskjellige busstopp på hver.',
      'Større busser, flere busser, raskere busser, AtB gjør alle tre på 5ern.',
      'En gang gikk 5ern via Gryta og Lohove til Dragvoll.',
      'Før i tiden møttes alle bussene i Munkegata/Dronningens gate.',
      'AtB laget egen bussapp som het Bussøyet, men den var for sent etter Bartebuss.',
      'Det finnes mange bussapper.',
      'AtB sitt API er laget av italienere.',
      'AtB sitt API har italienske metodenavn.',
      'Bartebuss og ByBussen er de beste bussappene.',
      'Bussene sjekker inn med GPS på hvert stopp, cirka.',
      'Bussene som må kjøre langt mellom hvert stopp har upresis sanntid.',
      'busskartet.no er ganske morsomt.',
      'Han som laget busskartet.no må ha kost seg gløgg i hjæl med alle de små bussene sine.',
      'Sekkemannen sitter alltid på en utgave av Under Dusken for å unngå bakterier fra bussetet.',

      // Om orakelet
      'Bussorakelets wiki er på ntnu.no/wiki/display/FUIROS',
      'Bussorakelet kom til live i 1998.',
      'I 2002 begynte bussorakelet å besvare spørsmål via SMS.',
      'BussTUC betyr "Buss: The Understanding Computer".',
      'Orakelet består av tre hjerner: Den første kan beregning, den andre kan språk, den tredje forstår de to første.',
      'Orakelet forstår språk ved hjelp av et komplekst sett med regler skrevet i Prolog.',
      'Bussorakelet er den sentrale delen i FUIROS-prosjektet.',
      'Orakelet kan 4590 ord, 1204 stoppnavn, 80 busslinjer og 9970 navnevarianter.',
      'Orakelet forstår språk ved hjelp av 5000 språkregler.',
      'Orakelet kan 960 substantiv, 1100 verb og 450 adjektiv.',
      'Orakelets kodebase består av 130.500 linjer Prolog.',
      'Orakelet forstår språk ved hjelp av "Consensical Grammar" (CONtext SENSItive CompositionAL Grammar).',

      // Team Trafikk
      'AtB er tusen ganger bedre enn Team Trafikk var.',
      'I 2010 byttet Team Trafikk navn til AtB, og byttet eiere.',
      'Team Trafikk sine busser var hvite, gamle og slitne.',
      'Da Team Trafikk ble AtB ble alt mye bedre.',
      'Da Team Trafikk ble AtB fikk de miljøvennlige busser.',
      'Da Team Trafikk ble AtB fikk de grønnere busser.',
      'Da Team Trafikk ble AtB fikk de mobillett.',
      'Da Team Trafikk ble AtB fikk de nye kontorer.',
      'Da Team Trafikk ble AtB fikk de API-er som man kunne hente data fra.',
      'Da Team Trafikk ble AtB fant Roy Sindre en nøkkel til API-et, han spurte ikke om lov.',
      'Åpne bussdata var veldig lurt av AtB.',

      // Contributors
      'Christoffer Jun Marcussen har vært med å lage bussorakelet (2011-2012)',
      'Jon S Bratseth har vært med å lage bussorakelet (1996-1997)',
      'Magnus Raaum har vært med å lage bussorakelet (2010-2011)',
      'Martin Thorsen Ranang har vært med å lage bussorakelet (2001-2011)',
      'Marius Qvam Wollamo har vært med å lage bussorakelet (2012-2013)',
      'Runar Andersstuen har vært med å lage bussorakelet (2011-2012)',
      'Rune Martin Andersen har vært med å lage bussorakelet (2011-2012)',
      'Rune Sætre har vært med å lage bussorakelet (2000-2012)',
      'Tore Amble har vært med å lage bussorakelet (1996-2012)',
      'Tore Bruland har vært med å lage bussorakelet (2004-2011)',
      'Trond Bø Engell har vært med å lage bussorakelet (2011-2012)',
    ];
    var randomGreeting = greetings[Math.floor(Math.random() * greetings.length)];
    return randomGreeting;
  },

  // Private functions, do not use externally

  shorten: function(answer) {

    // Example:
    // "Holdeplassen nærmest Gløshaugen er Gløshaugen Syd. Buss 5 går fra
    // Gløshaugen Syd kl. 2054 til Prinsen kinosenter kl. 2058 og buss 19
    // går fra Prinsen kinosenter kl. 2105 til Studentersamfundet kl. 2106.
    // Tidene angir tidligste passeringer av holdeplassene."

    var pieces = answer.split('. ');

    // Slice away "Holdeplassen nærmest X er X."
    if (pieces[0].startsWith('Holdeplassen nærmest')) {
      pieces = pieces.slice(1);
    }

    // Slice away "Tidene angir tidligste passeringer av holdeplassene."
    if (pieces[pieces.length-1].startsWith('Tidene angir tidligste')) {
      pieces = pieces.slice(0, pieces.length-1);
    }

    return pieces.join('. ') + '.';
  },

}
<|endoftext|>


<commit_before>$(document).ready(function () {

    function inView() {
        var desktopOffset = 60;
        var caseBackgrd = $('[data-name="hnm"]').children(".o-featured__background").eq(0);
        var caseWidth = caseBackgrd.width();
        var caseLeftEdgePos = caseBackgrd.offset().left;
        var maxPos = $(window).width() - desktopOffset;
        var minPos = maxPos - caseWidth;
        var inView = ((caseLeftEdgePos >= minPos) && (caseLeftEdgePos <= maxPos));
        return inView;
    }

    function invertir() {
        if (inView()) {
            $(".c-ui__logo").html("Aye");
        }
        else {
            $(".c-ui__logo").html("Nay");
        }
    }

	$(".o-featured__case").hover(function () {
	    var dark = $(this).attr("data-isDark");
	    if (dark == "0") {
	        $(".c-ui__nav-items.js-invert").addClass("invert");
	    }
	    else {
	        $(".c-ui__nav-items.js-invert").removeClass("invert");
	    }
	}, function () {
	    var dark = $(this).attr("data-isDark");
	    if (dark == "0") {
	        $(".c-ui__nav-items.js-invert").addClass("invert");
	    }
	    else {
	        $(".c-ui__nav-items.js-invert").removeClass("invert");
	    }
		});

	$('body').on('mousewheel DOMMouseScroll', function (e) {
		if (typeof e.originalEvent.detail == 'number' && e.originalEvent.detail !== 0) {
			invertir();
			/*if (e.originalEvent.detail > 0) {
				console.log('Down');
			} else if (e.originalEvent.detail < 0) {
				console.log('Up');
			}*/
		} else if (typeof e.originalEvent.wheelDelta == 'number') {
			invertir();
			/*if (e.originalEvent.wheelDelta < 0) {
				console.log('Down');
			} else if (e.originalEvent.wheelDelta > 0) {
				console.log('Up');
			}*/
		}
	});
});

/*($('[data-name="hnm"]').offset().left > $(window).width() - 60 - $('[data-name="hnm"]').width()) && ($('[data-name="hnm"]').offset().left < $(window).width() - 60)
var child = o - featured__background
$('[data-name="hnm"]').children(".o-featured__background").eq(0).width();*/<commit_msg>added wheel<commit_after>$(document).ready(function () {

    function inView() {
        var desktopOffset = 60;
        var caseBackgrd = $('[data-name="hnm"]').children(".o-featured__background").eq(0);
        var caseWidth = caseBackgrd.width();
        var caseLeftEdgePos = caseBackgrd.offset().left;
        var maxPos = $(window).width() - desktopOffset;
        var minPos = maxPos - caseWidth;
        var inView = ((caseLeftEdgePos >= minPos) && (caseLeftEdgePos <= maxPos));
        return inView;
    }

    function invertir() {
        if (inView()) {
            $(".c-ui__logo").html("Aye");
        }
        else {
            $(".c-ui__logo").html("Nay");
        }
    }

	$(".o-featured__case").hover(function () {
	    var dark = $(this).attr("data-isDark");
	    if (dark == "0") {
	        $(".c-ui__nav-items.js-invert").addClass("invert");
	    }
	    else {
	        $(".c-ui__nav-items.js-invert").removeClass("invert");
	    }
	}, function () {
	    var dark = $(this).attr("data-isDark");
	    if (dark == "0") {
	        $(".c-ui__nav-items.js-invert").addClass("invert");
	    }
	    else {
	        $(".c-ui__nav-items.js-invert").removeClass("invert");
	    }
		});

	$('body').on('mousewheel DOMMouseScroll', function (e) {
		if (typeof e.originalEvent.detail == 'number' && e.originalEvent.detail !== 0) {
			invertir();
			/*if (e.originalEvent.detail > 0) {
				console.log('Down');
			} else if (e.originalEvent.detail < 0) {
				console.log('Up');
			}*/
		} else if (typeof e.originalEvent.wheelDelta == 'number') {
			invertir();
			/*if (e.originalEvent.wheelDelta < 0) {
				console.log('Down');
			} else if (e.originalEvent.wheelDelta > 0) {
				console.log('Up');
			}*/
		}
	});

	$(window).on('wheel', function (event) {
		invertir();
		// deltaY obviously records vertical scroll, deltaX and deltaZ exist too
		if (event.originalEvent.deltaY < 0) {
			// wheeled up
		}
		else {
			// wheeled down
		}
	});
});

/*($('[data-name="hnm"]').offset().left > $(window).width() - 60 - $('[data-name="hnm"]').width()) && ($('[data-name="hnm"]').offset().left < $(window).width() - 60)
var child = o - featured__background
$('[data-name="hnm"]').children(".o-featured__background").eq(0).width();*/<|endoftext|>


<commit_before>// app namespace
var paintr = paintr || {};

/**
 * Handler for drawing rectangles and squares
 */
paintr.drawRect = function() {
  paintr.toggleMode();
  var is_drawing = false;
  var rect,
      mouse_pos,
      x0, y0;

  paintr.canvas.on('mouse:down', function(e) {
    mouse_pos = paintr.canvas.getPointer(e.e);
    x0 = mouse_pos.x;
    y0 = mouse_pos.y;
    is_drawing = true;
    rect = new fabric.Rect({
      width: 0,
      height: 0,
      left: x0,
      top: y0,
      fill: '',
      stroke: paintr.pen_color
    });
    paintr.canvas.add(rect);
  });

  paintr.canvas.on('mouse:move', function(e) {
    if (!is_drawing) return;
    mouse_pos = paintr.canvas.getPointer(e.e);
    var w = mouse_pos.x - x0,
        h = mouse_pos.y - y0;
    rect.set({ width: w, height: h});
    paintr.canvas.renderAll();
  });

  paintr.canvas.on('mouse:up', function(e) {
    is_drawing = false;
  });
}

/**
 * Handler to draw a straight line. Mouse down, move, and up events handled
 */
paintr.drawLine = function() {
  paintr.toggleMode();
  var is_drawing = false;
  var line;

  paintr.canvas.on('mouse:down', function(e) {
    var mouse_pos = paintr.canvas.getPointer(e.e);
    is_drawing = true;
    line = new fabric.Line([mouse_pos.x, mouse_pos.y, mouse_pos.x, mouse_pos.y], {
      strokeWidth: 2,
      fill: paintr.pen_color,
      stroke: paintr.pen_color
    });
    paintr.canvas.add(line);
  });

  paintr.canvas.on('mouse:move', function(e) {
    if (!is_drawing) return;
    var mouse_pos = paintr.canvas.getPointer(e.e);
    line.set({ x2: mouse_pos.x, y2: mouse_pos.y });
    paintr.canvas.renderAll();
    paintr.canvas.calcOffset();
  });

  paintr.canvas.on('mouse:up', function(e) {
    is_drawing = false;
  });
}

/**
 * Handler for freehand drawing
 */
paintr.drawFreehand = function() {
  paintr.toggleMode();
  paintr.canvas.isDrawingMode = true;
  paintr.canvas.renderAll();
}

/**
 * Handler for selection and moving
 */
paintr.select = function() {
  paintr.toggleMode();
  paintr.canvas.selection = true;
  paintr.canvas.forEachObject(function(obj) {
    obj.selectable = true;
    obj.setCoords();
  });
  paintr.canvas.calcOffset();
  paintr.canvas.renderAll();
}

/**
 * Resets canvas handlers. Should be called whenever the mode is changed
 */
paintr.toggleMode = function() {
  paintr.canvas.off('mouse:down');
  paintr.canvas.off('mouse:up');
  paintr.canvas.off('mouse:move');
  paintr.canvas.isDrawingMode = false;
  paintr.canvas.selection = false;
  paintr.canvas.forEachObject(function(obj) {
    obj.selectable = false;
  });
}

/**
 * Changes the pen color
 * @param color - color to be changed to
 */
paintr.color = function(color) {
  paintr.pen_color = color;
  paintr.canvas.freeDrawingBrush.color = paintr.pen_color;
}

/**
 * Clears the canvas of all objects
 */
paintr.clear = function() {
  paintr.canvas.clear();
}

// Setup the canvas
window.onload = function() {
  paintr.canvas = new fabric.Canvas('canvas', { selection: true });
  paintr.canvas.backgroundColor = 'white';
  paintr.pen_color = 'black';
  paintr.canvas.freeDrawingBrush.width = 2;
  paintr.canvas.renderAll();

  // EVENT LISTENERS
  document.getElementById('line').addEventListener('click', paintr.drawLine);
  document.getElementById('freehand').addEventListener('click', paintr.drawFreehand);
  document.getElementById('select').addEventListener('click', paintr.select);
  document.getElementById('clear').addEventListener('click', paintr.clear);
  document.getElementById('rectangle').addEventListener('click', paintr.drawRect);
}<commit_msg>cut and paste (partially working)<commit_after>// app namespace
var paintr = paintr || {};

//app attributes
paintr.clipboardArray = new Array();
paintr.clipboardObject = null;

/**
 * Handler for drawing rectangles and squares
 */
paintr.drawRect = function() {
  paintr.toggleMode();
  var is_drawing = false;
  var rect,
      mouse_pos,
      x0, y0;

  paintr.canvas.on('mouse:down', function(e) {
    mouse_pos = paintr.canvas.getPointer(e.e);
    x0 = mouse_pos.x;
    y0 = mouse_pos.y;
    is_drawing = true;
    rect = new fabric.Rect({
      width: 0,
      height: 0,
      left: x0,
      top: y0,
      fill: '',
      stroke: paintr.pen_color
    });
    paintr.canvas.add(rect);
  });

  paintr.canvas.on('mouse:move', function(e) {
    if (!is_drawing) return;
    mouse_pos = paintr.canvas.getPointer(e.e);
    var w = mouse_pos.x - x0,
        h = mouse_pos.y - y0;
    rect.set({ width: w, height: h});
    paintr.canvas.renderAll();
  });

  paintr.canvas.on('mouse:up', function(e) {
    is_drawing = false;
  });
}

/**
 * Handler to draw a straight line. Mouse down, move, and up events handled
 */
paintr.drawLine = function() {
  paintr.toggleMode();
  var is_drawing = false;
  var line;

  paintr.canvas.on('mouse:down', function(e) {
    var mouse_pos = paintr.canvas.getPointer(e.e);
    is_drawing = true;
    line = new fabric.Line([mouse_pos.x, mouse_pos.y, mouse_pos.x, mouse_pos.y], {
      strokeWidth: 2,
      fill: paintr.pen_color,
      stroke: paintr.pen_color
    });
    paintr.canvas.add(line);
  });

  paintr.canvas.on('mouse:move', function(e) {
    if (!is_drawing) return;
    var mouse_pos = paintr.canvas.getPointer(e.e);
    line.set({ x2: mouse_pos.x, y2: mouse_pos.y });
    paintr.canvas.renderAll();
    paintr.canvas.calcOffset();
  });

  paintr.canvas.on('mouse:up', function(e) {
    is_drawing = false;
  });
}

/**
 * Handler for freehand drawing
 */
paintr.drawFreehand = function() {
  paintr.toggleMode();
  paintr.canvas.isDrawingMode = true;
  paintr.canvas.renderAll();
}

/**
 * Handler for selection and moving
 */
paintr.select = function() {
  paintr.toggleMode();
  paintr.canvas.selection = true;
  paintr.canvas.forEachObject(function(obj) {
    obj.selectable = true;
    obj.setCoords();
  });
  paintr.canvas.calcOffset();
  paintr.canvas.renderAll();
}

/**
 * Resets canvas handlers. Should be called whenever the mode is changed
 */
paintr.toggleMode = function() {
  paintr.canvas.off('mouse:down');
  paintr.canvas.off('mouse:up');
  paintr.canvas.off('mouse:move');
  paintr.canvas.isDrawingMode = false;
  paintr.canvas.selection = false;
  paintr.canvas.forEachObject(function(obj) {
    obj.selectable = false;
  });
}

/**
 * Changes the pen color
 * @param color - color to be changed to
 */
paintr.color = function(color) {
  paintr.pen_color = color;
  paintr.canvas.freeDrawingBrush.color = paintr.pen_color;
}

paintr.cut = function(){
      clipboardArray = new Array();

  if(paintr.canvas.getActiveGroup()){
    for(var i in paintr.canvas.getActiveGroup().objects){
      //var object = fabric.util.object.clone(paintr.canvas.getActiveGroup().objects[i]);
      paintr.clipboardArray[i] = paintr.canvas.getActiveGroup().objects[i];
    }
    paintr.canvas.getActiveGroup().forEachObject(function(o){ paintr.canvas.remove(o) });
    paintr.canvas.discardActiveGroup().renderAll();
  }else if(paintr.canvas.getActiveObject()){
    //var object = fabric.util.object.clone(paintr.canvas.getActiveObject());
    paintr.clipboardObject = paintr.canvas.getActiveObject();
    paintr.canvas.remove(paintr.canvas.getActiveObject());
    paintr.canvas.discardActiveObject().renderAll();
  }
}

paintr.paste = function(){
  if(paintr.clipboardArray.length > 0){
    for(var i in paintr.clipboardArray){
      paintr.canvas.add(paintr.clipboardArray[i]);
      paintr.clipboardArray[i].setCoords();
    }
  }else if(paintr.clipboardObject){
    paintr.canvas.add(paintr.clipboardObject);
    paintr.clipboardObject.setCoords();
  }
  paintr.canvas.renderAll();
}

paintr.onKeyDownHandler=function(event) {
    var key;
    if(window.event){
        key = window.event.keyCode;
    }
    else{
        key = event.keyCode;
    }
    switch(key){

        case 88: // Cut (Ctrl+X)
            if(event.ctrlKey){
                event.preventDefault();
                paintr.cut();
            }
            break;
        case 86: // Paste (Ctrl+V)
            if(event.ctrlKey){
                event.preventDefault();
                paintr.paste();
            }
            break;
        default:
            break;
    }
}

/**
 * Clears the canvas of all objects
 */
paintr.clear = function() {
  paintr.canvas.clear();
}

// Setup the canvas
window.onload = function() {
  paintr.canvas = new fabric.Canvas('canvas', { selection: true });
  paintr.canvas.backgroundColor = 'white';
  paintr.pen_color = 'black';
  paintr.canvas.freeDrawingBrush.width = 2;
  paintr.canvas.renderAll();

  // EVENT LISTENERS
  document.getElementById('line').addEventListener('click', paintr.drawLine);
  document.getElementById('freehand').addEventListener('click', paintr.drawFreehand);
  document.getElementById('select').addEventListener('click', paintr.select);
  document.getElementById('clear').addEventListener('click', paintr.clear);
  document.getElementById('rectangle').addEventListener('click', paintr.drawRect);
  document.onkeydown = paintr.onKeyDownHandler;

}<|endoftext|>


<commit_before>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors');
const { TRUNCATE } = require ('./base/functions/number');

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

module.exports = class phemex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'phemex',
            'name': 'Phemex',
            'countries': [ 'CN' ], // China
            'rateLimit': 100,
            'version': 'v1',
            'certified': false,
            'pro': true,
            'has': {
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/83165440-2f1cf200-a116-11ea-9046-a255d09fb2ed.jpg',
                'test': {
                    'public': 'https://testnet-api.phemex.com/exchange/public',
                    'private': 'https://testnet-api.phemex.com',
                },
                'api': {
                    'public': 'https://api.phemex.com/exchange/public',
                    // 'public': 'https://api.phemex.com',
                    'private': 'https://api.phemex.com',
                },
                'www': 'https://phemex.com',
                'doc': 'https://github.com/phemex/phemex-api-docs',
                'fees': 'https://phemex.com/fees-conditions',
                'referral': 'https://phemex.com/register?referralCode=EDNVJ',
            },
            'api': {
                'public': {
                    'get': [
                        'cfg/v2/products', // spot + contracts
                        'products', // contracts only
                        'nomics/trades', // ?market=<symbol>&since=<since>
                    ],
                },
                'v1': {
                    'get': [
                        'v1/md/orderbook', // ?symbol=<symbol>&id=<id>
                        'v1/md/orderbook', // ?symbol=sBTCUSDT
                        'v1/md/orderbook', // ?symbol=<symbol>&id=<id>
                        'v1/md/orderbook', // ?symbol=BTCUSD
                        'v1/md/trade', // ?symbol=<symbol>&id=<id>
                        'v1/md/trade', // ?symbol=BTCUSD
                        'v1/md/ticker/24hr', // ?symbol=<symbol>&id=<id>
                        'v1/md/ticker/24hr', // ?symbol=BTCUSD
                        'v1/md/ticker/24hr/all', // ?id=<id>
                        'v1/md/ticker/24hr/all',
                        'v1/exchange/public/products', // contracts only
                    ],
                },
                'v0': {
                    'get': [
                        'md/orderbook', // ?symbol=<symbol>&id=<id>
                        'md/orderbook', // ?symbol=sBTCUSDT
                        'md/orderbook', // ?symbol=<symbol>&id=<id>
                        'md/orderbook', // ?symbol=BTCUSD
                        'md/trade', // ?symbol=<symbol>&id=<id>
                        'md/trade', // ?symbol=sBTCUSDT
                        'md/trade', // ?symbol=<symbol>&id=<id>
                        'md/trade', // ?symbol=BTCUSD
                        'md/spot/ticker/24hr', // ?symbol=<symbol>&id=<id>
                        'md/spot/ticker/24hr', // ?symbol=sBTCUSDT
                        'md/ticker/24hr', // ?symbol=<symbol>&id=<id>
                        'md/ticker/24hr', // ?symbol=BTCUSD
                    ],
                },
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'taker': 0.1 / 100,
                    'maker': 0.1 / 100,
                },
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
            },
            'exceptions': {
                'exact': {
                },
                'broad': {
                },
            },
            'options': {
            },
        });
    }

    async fetchMarkets (params = {}) {
        const response = await this.publicGetCfgV2Products (params);
        //
        //     {
        //         "code":0,
        //         "msg":"OK",
        //         "data":{
        //             "ratioScale":8,
        //             "currencies":[
        //                 {"currency":"BTC","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"Bitcoin"},
        //                 {"currency":"USD","valueScale":4,"minValueEv":1,"maxValueEv":500000000000000,"name":"USD"},
        //                 {"currency":"USDT","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"TetherUS"},
        //             ],
        //             "products":[
        //                 {
        //                     "symbol":"BTCUSD",
        //                     "displaySymbol":"BTC / USD",
        //                     "indexSymbol":".BTC",
        //                     "markSymbol":".MBTC",
        //                     "fundingRateSymbol":".BTCFR",
        //                     "fundingRate8hSymbol":".BTCFR8H",
        //                     "contractUnderlyingAssets":"USD",
        //                     "settleCurrency":"BTC",
        //                     "quoteCurrency":"USD",
        //                     "contractSize":1.0,
        //                     "lotSize":1,
        //                     "tickSize":0.5,
        //                     "priceScale":4,
        //                     "ratioScale":8,
        //                     "pricePrecision":1,
        //                     "minPriceEp":5000,
        //                     "maxPriceEp":10000000000,
        //                     "maxOrderQty":1000000,
        //                     "type":"Perpetual"
        //                 },
        //                 {
        //                     "symbol":"sBTCUSDT",
        //                     "displaySymbol":"BTC / USDT",
        //                     "quoteCurrency":"USDT",
        //                     "pricePrecision":2,
        //                     "type":"Spot",
        //                     "baseCurrency":"BTC",
        //                     "baseTickSize":"0.000001 BTC",
        //                     "baseTickSizeEv":100,
        //                     "quoteTickSize":"0.01 USDT",
        //                     "quoteTickSizeEv":1000000,
        //                     "minOrderValue":"10 USDT",
        //                     "minOrderValueEv":1000000000,
        //                     "maxBaseOrderSize":"1000 BTC",
        //                     "maxBaseOrderSizeEv":100000000000,
        //                     "maxOrderValue":"5,000,000 USDT",
        //                     "maxOrderValueEv":500000000000000,
        //                     "defaultTakerFee":"0.001",
        //                     "defaultTakerFeeEr":100000,
        //                     "defaultMakerFee":"0.001",
        //                     "defaultMakerFeeEr":100000,
        //                     "baseQtyPrecision":6,
        //                     "quoteQtyPrecision":2
        //                 },
        //             ],
        //             "riskLimits":[
        //                 {
        //                     "symbol":"BTCUSD",
        //                     "steps":"50",
        //                     "riskLimits":[
        //                         {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
        //                         {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
        //                         {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
        //                     ]
        //                 },
        //             ],
        //             "leverages":[
        //                 {"initialMargin":"1.0%","initialMarginEr":1000000,"options":[1,2,3,5,10,25,50,100]},
        //                 {"initialMargin":"1.5%","initialMarginEr":1500000,"options":[1,2,3,5,10,25,50,66]},
        //                 {"initialMargin":"2.0%","initialMarginEr":2000000,"options":[1,2,3,5,10,25,33,50]},
        //             ]
        //         }
        //     }
        //
        const data = this.safeValue (response, 'data', {});
        const products = this.safeValue (data, 'products', []);
        const riskLimits = this.safeValue (data, 'riskLimits', []);
        const result = [];
        for (let i = 0; i < products.length; i++) {
            const market = products[i];
            const id = this.safeString (market, 'symbol');
            const type = this.safeStringLower (market, 'type');
            if (type === 'perpetual') {
            } else if (type === 'spot') {
            }
            const id = this.safeString (market, 'market');
            const baseId = this.safeString (market, 'base');
            const quoteId = this.safeString (market, 'quote');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const symbol = base + '/' + quote;
            const status = this.safeString (market, 'status');
            const active = (status === 'trading');
            const baseCurrency = this.safeValue (currenciesById, baseId);
            let amountPrecision = undefined;
            if (baseCurrency !== undefined) {
                amountPrecision = this.safeInteger (baseCurrency, 'decimals', 8);
            }
            const precision = {
                'price': this.safeInteger (market, 'pricePrecision'),
                'amount': amountPrecision,
            };
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
                'active': active,
                'precision': precision,
                'limits': {
                    'amount': {
                        'min': this.safeFloat (market, 'minOrderInBaseAsset'),
                        'max': undefined,
                    },
                    'price': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'cost': {
                        'min': this.safeFloat (market, 'minOrderInQuoteAsset'),
                        'max': undefined,
                    },
                },
            });
        }
        return result;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        const query = this.omit (params, this.extractParams (path));
        let url = '/' + this.implodeParams (path, params);
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        }
        // const getOrDelete = (method === 'GET') || (method === 'DELETE');
        // if (getOrDelete) {
        //     if (Object.keys (query).length) {
        //         url += '?' + this.urlencode (query);
        //     }
        // }
        // if (api === 'private') {
        //     this.checkRequiredCredentials ();
        //     let payload = '';
        //     if (!getOrDelete) {
        //         if (Object.keys (query).length) {
        //             body = this.json (query);
        //             payload = body;
        //         }
        //     }
        //     const timestamp = this.milliseconds ().toString ();
        //     const auth = timestamp + method + url + payload;
        //     const signature = this.hmac (this.encode (auth), this.encode (this.secret));
        //     headers = {
        //     };
        //     if (!getOrDelete) {
        //         headers['Content-Type'] = 'application/json';
        //     }
        // }
        url = this.urls['api'][api] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        if (response === undefined) {
            return; // fallback to default error handler
        }
        //
        //     {"errorCode":308,"error":"The signature length is invalid (HMAC-SHA256 should return a 64 length hexadecimal string)."}
        //     {"errorCode":203,"error":"symbol parameter is required."}
        //     {"errorCode":205,"error":"symbol parameter is invalid."}
        //
        const errorCode = this.safeString (response, 'errorCode');
        const error = this.safeString (response, 'error');
        if (errorCode !== undefined) {
            const feedback = this.id + ' ' + body;
            this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
            this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
            throw new ExchangeError (feedback); // unknown message
        }
    }
};
<commit_msg>phemex fetchMarkets, endpoints wip<commit_after>'use strict';

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

const Exchange = require ('./base/Exchange');
const { ExchangeError, BadSymbol, AuthenticationError, InsufficientFunds, InvalidOrder, ArgumentsRequired, OrderNotFound, InvalidAddress, BadRequest, RateLimitExceeded, PermissionDenied, ExchangeNotAvailable, AccountSuspended, OnMaintenance } = require ('./base/errors');
const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');

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

module.exports = class phemex extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'phemex',
            'name': 'Phemex',
            'countries': [ 'CN' ], // China
            'rateLimit': 100,
            'version': 'v1',
            'certified': false,
            'pro': true,
            'has': {
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/83165440-2f1cf200-a116-11ea-9046-a255d09fb2ed.jpg',
                'test': {
                    'public': 'https://testnet-api.phemex.com/exchange/public',
                    'private': 'https://testnet-api.phemex.com',
                },
                'api': {
                    'public': 'https://api.phemex.com/exchange/public',
                    // 'public': 'https://api.phemex.com',
                    'private': 'https://api.phemex.com',
                },
                'www': 'https://phemex.com',
                'doc': 'https://github.com/phemex/phemex-api-docs',
                'fees': 'https://phemex.com/fees-conditions',
                'referral': 'https://phemex.com/register?referralCode=EDNVJ',
            },
            'api': {
                'public': {
                    'get': [
                        'cfg/v2/products', // spot + contracts
                        'products', // contracts only
                        'nomics/trades', // ?market=<symbol>&since=<since>
                    ],
                },
                'v1': {
                    'get': [
                        'v1/md/orderbook', // ?symbol=<symbol>&id=<id>
                        'v1/md/trade', // ?symbol=<symbol>&id=<id>
                        'v1/md/ticker/24hr', // ?symbol=<symbol>&id=<id>
                        'v1/md/ticker/24hr/all', // ?id=<id>
                        'v1/exchange/public/products', // contracts only
                    ],
                },
                'v0': {
                    'get': [
                        'md/orderbook', // ?symbol=<symbol>&id=<id>
                        'md/trade', // ?symbol=<symbol>&id=<id>
                        'md/spot/ticker/24hr', // ?symbol=<symbol>&id=<id>
                        'md/ticker/24hr', // ?symbol=<symbol>&id=<id>
                    ],
                },
            },
            'precisionMode': TICK_SIZE,
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'taker': 0.1 / 100,
                    'maker': 0.1 / 100,
                },
            },
            'requiredCredentials': {
                'apiKey': true,
                'secret': true,
            },
            'exceptions': {
                'exact': {
                },
                'broad': {
                },
            },
            'options': {
            },
        });
    }

    parseSafeFloat (value = undefined) {
        if (value === undefined) {
            return value;
        }
        value = value.replace (',', '');
        const parts = value.split (' ');
        return this.safeFloat (parts, 0);
    }

    async fetchMarkets (params = {}) {
        const response = await this.publicGetCfgV2Products (params);
        //
        //     {
        //         "code":0,
        //         "msg":"OK",
        //         "data":{
        //             "ratioScale":8,
        //             "currencies":[
        //                 {"currency":"BTC","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"Bitcoin"},
        //                 {"currency":"USD","valueScale":4,"minValueEv":1,"maxValueEv":500000000000000,"name":"USD"},
        //                 {"currency":"USDT","valueScale":8,"minValueEv":1,"maxValueEv":5000000000000000000,"name":"TetherUS"},
        //             ],
        //             "products":[
        //                 {
        //                     "symbol":"BTCUSD",
        //                     "displaySymbol":"BTC / USD",
        //                     "indexSymbol":".BTC",
        //                     "markSymbol":".MBTC",
        //                     "fundingRateSymbol":".BTCFR",
        //                     "fundingRate8hSymbol":".BTCFR8H",
        //                     "contractUnderlyingAssets":"USD",
        //                     "settleCurrency":"BTC",
        //                     "quoteCurrency":"USD",
        //                     "contractSize":1.0,
        //                     "lotSize":1,
        //                     "tickSize":0.5,
        //                     "priceScale":4,
        //                     "ratioScale":8,
        //                     "pricePrecision":1,
        //                     "minPriceEp":5000,
        //                     "maxPriceEp":10000000000,
        //                     "maxOrderQty":1000000,
        //                     "type":"Perpetual"
        //                 },
        //                 {
        //                     "symbol":"sBTCUSDT",
        //                     "displaySymbol":"BTC / USDT",
        //                     "quoteCurrency":"USDT",
        //                     "pricePrecision":2,
        //                     "type":"Spot",
        //                     "baseCurrency":"BTC",
        //                     "baseTickSize":"0.000001 BTC",
        //                     "baseTickSizeEv":100,
        //                     "quoteTickSize":"0.01 USDT",
        //                     "quoteTickSizeEv":1000000,
        //                     "minOrderValue":"10 USDT",
        //                     "minOrderValueEv":1000000000,
        //                     "maxBaseOrderSize":"1000 BTC",
        //                     "maxBaseOrderSizeEv":100000000000,
        //                     "maxOrderValue":"5,000,000 USDT",
        //                     "maxOrderValueEv":500000000000000,
        //                     "defaultTakerFee":"0.001",
        //                     "defaultTakerFeeEr":100000,
        //                     "defaultMakerFee":"0.001",
        //                     "defaultMakerFeeEr":100000,
        //                     "baseQtyPrecision":6,
        //                     "quoteQtyPrecision":2
        //                 },
        //             ],
        //             "riskLimits":[
        //                 {
        //                     "symbol":"BTCUSD",
        //                     "steps":"50",
        //                     "riskLimits":[
        //                         {"limit":100,"initialMargin":"1.0%","initialMarginEr":1000000,"maintenanceMargin":"0.5%","maintenanceMarginEr":500000},
        //                         {"limit":150,"initialMargin":"1.5%","initialMarginEr":1500000,"maintenanceMargin":"1.0%","maintenanceMarginEr":1000000},
        //                         {"limit":200,"initialMargin":"2.0%","initialMarginEr":2000000,"maintenanceMargin":"1.5%","maintenanceMarginEr":1500000},
        //                     ]
        //                 },
        //             ],
        //             "leverages":[
        //                 {"initialMargin":"1.0%","initialMarginEr":1000000,"options":[1,2,3,5,10,25,50,100]},
        //                 {"initialMargin":"1.5%","initialMarginEr":1500000,"options":[1,2,3,5,10,25,50,66]},
        //                 {"initialMargin":"2.0%","initialMarginEr":2000000,"options":[1,2,3,5,10,25,33,50]},
        //             ]
        //         }
        //     }
        //
        const data = this.safeValue (response, 'data', {});
        const products = this.safeValue (data, 'products', []);
        const riskLimits = this.safeValue (data, 'riskLimits', []);
        const riskLimitsById = this.indexBy (riskLimits, 'symbol');
        const result = [];
        for (let i = 0; i < products.length; i++) {
            let market = products[i];
            const id = this.safeString (market, 'symbol');
            const type = this.safeStringLower (market, 'type');
            const quoteId = this.safeString (market, 'quoteCurrency');
            let baseId = undefined;
            let limits = undefined;
            let spot = undefined;
            let future = undefined;
            let precision = undefined;
            let taker = undefined;
            let maker = undefined;
            if (type === 'perpetual') {
                future = true;
                spot = false;
                const riskLimitValues = this.safeValue (riskLimitsById, id, {});
                market = this.extend (market, riskLimitValues);
                console.log (market);
                process.exit ();
                continue;
            } else if (type === 'spot') {
                baseId = this.safeString (market, 'baseCurrency');
                spot = true;
                future = false;
                taker = this.safeFloat (market, 'defaultTakerFee');
                maker = this.safeFloat (market, 'defaultMakerFee');
                precision = {
                    'amount': this.parseSafeFloat (this.safeString (market, 'baseTickSize')),
                    'price': this.parseSafeFloat (this.safeString (market, 'quoteTickSize')),
                };
                limits = {
                    'amount': {
                        'min': precision['amount'],
                        'max': this.parseSafeFloat (this.safeString (market, 'maxBaseOrderSize')),
                    },
                    'price': {
                        'min': precision['price'],
                        'max': undefined,
                    },
                    'cost': {
                        'min': this.parseSafeFloat (this.safeString (market, 'minOrderValue')),
                        'max': this.parseSafeFloat (this.safeString (market, 'maxOrderValue')),
                    },
                };
            }
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const symbol = base + '/' + quote;
            const active = undefined;
            // const baseCurrency = this.safeValue (currenciesById, baseId);
            // let amountPrecision = undefined;
            // if (baseCurrency !== undefined) {
            //     amountPrecision = this.safeInteger (baseCurrency, 'decimals', 8);
            // }
            // const precision = {
            //     'price': this.safeInteger (market, 'pricePrecision'),
            //     'amount': amountPrecision,
            // };
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'baseId': baseId,
                'quoteId': quoteId,
                'info': market,
                'type': type,
                'spot': spot,
                'future': future,
                'active': active,
                'taker': taker,
                'maker': maker,
                'precision': precision,
                'limits': limits,
            });
        }
        return result;
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        const query = this.omit (params, this.extractParams (path));
        let url = '/' + this.implodeParams (path, params);
        if (api === 'public') {
            if (Object.keys (query).length) {
                url += '?' + this.urlencode (query);
            }
        }
        // const getOrDelete = (method === 'GET') || (method === 'DELETE');
        // if (getOrDelete) {
        //     if (Object.keys (query).length) {
        //         url += '?' + this.urlencode (query);
        //     }
        // }
        // if (api === 'private') {
        //     this.checkRequiredCredentials ();
        //     let payload = '';
        //     if (!getOrDelete) {
        //         if (Object.keys (query).length) {
        //             body = this.json (query);
        //             payload = body;
        //         }
        //     }
        //     const timestamp = this.milliseconds ().toString ();
        //     const auth = timestamp + method + url + payload;
        //     const signature = this.hmac (this.encode (auth), this.encode (this.secret));
        //     headers = {
        //     };
        //     if (!getOrDelete) {
        //         headers['Content-Type'] = 'application/json';
        //     }
        // }
        url = this.urls['api'][api] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        if (response === undefined) {
            return; // fallback to default error handler
        }
        //
        //     {"errorCode":308,"error":"The signature length is invalid (HMAC-SHA256 should return a 64 length hexadecimal string)."}
        //     {"errorCode":203,"error":"symbol parameter is required."}
        //     {"errorCode":205,"error":"symbol parameter is invalid."}
        //
        const errorCode = this.safeString (response, 'errorCode');
        const error = this.safeString (response, 'error');
        if (errorCode !== undefined) {
            const feedback = this.id + ' ' + body;
            this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
            this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
            throw new ExchangeError (feedback); // unknown message
        }
    }
};
<|endoftext|>