<commit_before>import { _parseAM, getAssetManager } from './assetManagers.js'
import {
  retrieve,
  insert,
  amend,
  deactivate,
  reactivate,
  searchDomains,
  checkDomains,
  insertDomain,
  retrieveEODBooks,
  getCredentialsForPubSub
} from './assetManagers.js'
import AssetManager from '../../assetManagers/AssetManager/assetManager.js'
import Domain from '../../assetManagers/Domain/domain'
import * as api from '../../exports/api'
import * as network from '../network'

network.retrieveData = jest.fn()
network.insertData = jest.fn()
network.patchData = jest.fn()
network.putData = jest.fn()
network.searchData = jest.fn()
network.deleteData = jest.fn()

api.config({
  stage: 'staging',
  token: process.env.API_TOKEN
})
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000

describe('utils/assetManagers', () => {
  describe('_parseAM function', () => {
    it('should return an instance of AssetManager class', () => {
      const json = {
        assetManagerId: '48576',
        clientId: 'testClient',
        defaultTimezone: 'UTC',
        version: 1
      }
      const parsedAM = _parseAM(json)
      const expectedClass = new AssetManager({
        assetManagerId: '48576',
        clientId: 'testClient',
        defaultTimezone: 'UTC',
        version: 1
      })
      expect(parsedAM).toEqual(expectedClass)
    })
  })

  describe('retrieve', () => {
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve({ assetManagerId: 1 })
      )
    })
    it('returns promise', () => {
      let promise = retrieve({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })

    it('calls retrieveData with the correct params', done => {
      retrieve({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1
        })
        done()
      })
    })

    describe('it returns the correct result', () => {
      test('with callback', done => {
        retrieve({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager({ assetManagerId: 1 }))
          done()
        })
      })
      test('with promise', () => {
        retrieve({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager({ assetManagerId: 1 }))
        })
      })
    })
  })

  describe('insert', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.insertData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = insert({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })

    test('calls insertData with correct params', done => {
      insert({ assetManager: data }, (error, result) => {
        expect(network.insertData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          data: JSON.parse(JSON.stringify(data))
        })
        done()
      })
    })

    describe('returns correct result', () => {
      test('with callback', done => {
        insert({ assetManager: data }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        insert({ assetManager: data }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('amend', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.putData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = amend({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls putData with correct params', done => {
      amend({ AMId: 1, assetManager: data }, (error, result) => {
        expect(network.putData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: JSON.parse(JSON.stringify(data))
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        amend({ AMId: 1, assetManager: data }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        amend({ AMId: 1, assetManager: data }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('deactivate', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.patchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = deactivate({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls patchData with correctResult', done => {
      deactivate({ AMId: 1 }, (error, result) => {
        expect(network.patchData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: { assetManagerStatus: 'Inactive' }
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        deactivate({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        deactivate({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('reactivate', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.patchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = reactivate({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls patchData with correct params', done => {
      reactivate({ AMId: 1 }, (error, result) => {
        expect(network.patchData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: { assetManagerStatus: 'Active' }
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        reactivate({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        reactivate({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('searchDomains', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
      network.searchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = searchDomains({ AMId: 88, query: { isPrimary: true } })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls searchData with the correct params', done => {
      searchDomains(
        { AMId: 88, query: { isPrimary: true } },
        (error, result) => {
          expect(network.searchData).toHaveBeenCalledWith({
            AMaaSClass: 'assetManagerDomains',
            AMId: 88,
            query: { isPrimary: true }
          })
          done()
        }
      )
    })
  })

  describe('checkDomains', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
    })
    test('with promise', () => {
      network.retrieveData.mockImplementation(() => Promise.resolve(data))
      let promise = checkDomains({ domain: 'testDomain.com' })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveData with correct params', done => {
      network.retrieveData.mockImplementation(() => Promise.resolve(data))
      checkDomains({ domain: 'testDomain.com' }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerDomains',
          query: { domains: ['testDomain.com'], isPrimary: true }
        })
        done()
      })
    })
    it('returns an array', done => {
      network.retrieveData.mockImplementation(() => Promise.resolve([data]))
      checkDomains({ domain: 'testDomain.com' }, (error, result) => {
        expect(result).toEqual([new Domain(data)])
        done()
      })
    })
  })

  describe('insertDomain', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
      network.insertData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = insertDomain({ AMId: 1, domain: data })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls insertData with correct params', done => {
      insertDomain({ domain: data }, (error, result) => {
        expect(network.insertData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerDomains',
          AMId: 1,
          data
        })
        done()
      })
    })
  })

  describe('retrieveEODBooks', () => {
    const mockedEODBook = {
      assetManagerId: 1,
      utcCloseTime: '18:00:00',
      bookId: 'testID',
      eodBookStatus: 'testStatus'
    }
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve(mockedEODBook)
      )
    })
    it('returns promise', () => {
      let promise = retrieveEODBooks({ AMId: 1, bookID: 'ABC' })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveEODBooks with the correct params', done => {
      retrieveEODBooks({ AMId: 1, bookID: 'ABC' }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerEODBooks',
          AMId: 1,
          bookID: 'ABC'
        })
        done()
      })
    })
    it('calls retrieveEODBooks with the correct params', done => {
      retrieveEODBooks({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerEODBooks',
          AMId: 1
        })
        done()
      })
    })
  })

  describe('getCredentialsForPubSub', () => {
    const mockedCredentials = {
      credentials: {
        AccessKeyId: 'testAcccessKey',
        SecretAccessKey: 'testSecretKey',
        SessionToken: 'testSessionToken'
      },
      topics: ['topic1', 'topic2']
    }
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve(mockedCredentials)
      )
    })
    it('returns promise', () => {
      let promise = getCredentialsForPubSub({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveData with the correct params', done => {
      getCredentialsForPubSub({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerPubSubCredentials',
          AMId: 1
        })
        done()
      })
    })
  })
})
<commit_msg>Fix test. AMAAS-2080<commit_after>import { _parseAM, getAssetManager } from './assetManagers.js'
import {
  retrieve,
  insert,
  amend,
  deactivate,
  reactivate,
  searchDomains,
  checkDomains,
  insertDomain,
  retrieveEODBooks,
  getCredentialsForPubSub
} from './assetManagers.js'
import AssetManager from '../../assetManagers/AssetManager/assetManager.js'
import Domain from '../../assetManagers/Domain/domain'
import * as api from '../../exports/api'
import * as network from '../network'

network.retrieveData = jest.fn()
network.insertData = jest.fn()
network.patchData = jest.fn()
network.putData = jest.fn()
network.searchData = jest.fn()
network.deleteData = jest.fn()

api.config({
  stage: 'staging',
  token: process.env.API_TOKEN
})
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000

describe('utils/assetManagers', () => {
  describe('_parseAM function', () => {
    it('should return an instance of AssetManager class', () => {
      const json = {
        assetManagerId: '48576',
        clientId: 'testClient',
        defaultTimezone: 'UTC',
        version: 1
      }
      const parsedAM = _parseAM(json)
      const expectedClass = new AssetManager({
        assetManagerId: '48576',
        clientId: 'testClient',
        defaultTimezone: 'UTC',
        version: 1
      })
      expect(parsedAM).toEqual(expectedClass)
    })
  })

  describe('retrieve', () => {
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve({ assetManagerId: 1 })
      )
    })
    it('returns promise', () => {
      let promise = retrieve({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })

    it('calls retrieveData with the correct params', done => {
      retrieve({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1
        })
        done()
      })
    })

    describe('it returns the correct result', () => {
      test('with callback', done => {
        retrieve({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager({ assetManagerId: 1 }))
          done()
        })
      })
      test('with promise', () => {
        retrieve({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager({ assetManagerId: 1 }))
        })
      })
    })
  })

  describe('insert', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.insertData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = insert({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })

    test('calls insertData with correct params', done => {
      insert({ assetManager: data }, (error, result) => {
        expect(network.insertData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          data: JSON.parse(JSON.stringify(data))
        })
        done()
      })
    })

    describe('returns correct result', () => {
      test('with callback', done => {
        insert({ assetManager: data }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        insert({ assetManager: data }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('amend', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.putData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = amend({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls putData with correct params', done => {
      amend({ AMId: 1, assetManager: data }, (error, result) => {
        expect(network.putData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: JSON.parse(JSON.stringify(data))
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        amend({ AMId: 1, assetManager: data }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        amend({ AMId: 1, assetManager: data }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('deactivate', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.patchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = deactivate({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls patchData with correctResult', done => {
      deactivate({ AMId: 1 }, (error, result) => {
        expect(network.patchData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: { assetManagerStatus: 'Inactive' }
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        deactivate({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        deactivate({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('reactivate', () => {
    let data
    beforeAll(() => {
      data = {
        defaultBookCloseTime: '17:30:00',
        defaultTimezone: 'UTC',
        assetManagerType: 'Accredited Investor',
        clientId: 1,
        assetManagerStatus: 'Active',
        defaultBookOwnerId: 2
      }
      network.patchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = reactivate({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls patchData with correct params', done => {
      reactivate({ AMId: 1 }, (error, result) => {
        expect(network.patchData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagers',
          AMId: 1,
          data: { assetManagerStatus: 'Active' }
        })
        done()
      })
    })
    describe('returns correct result', () => {
      test('with callback', done => {
        reactivate({ AMId: 1 }, (error, result) => {
          expect(result).toEqual(new AssetManager(data))
          done()
        })
      })
      test('with promise', () => {
        reactivate({ AMId: 1 }).then(result => {
          expect(result).toEqual(new AssetManager(data))
        })
      })
    })
  })

  describe('searchDomains', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
      network.searchData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = searchDomains({ AMId: 88, query: { isPrimary: true } })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls searchData with the correct params', done => {
      searchDomains(
        { AMId: 88, query: { isPrimary: true } },
        (error, result) => {
          expect(network.searchData).toHaveBeenCalledWith({
            AMaaSClass: 'assetManagerDomains',
            AMId: 88,
            query: { isPrimary: true }
          })
          done()
        }
      )
    })
  })

  describe('checkDomains', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
    })
    test('with promise', () => {
      network.retrieveData.mockImplementation(() => Promise.resolve(data))
      let promise = checkDomains({ domain: 'testDomain.com' })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveData with correct params', done => {
      network.retrieveData.mockImplementation(() => Promise.resolve(data))
      checkDomains({ domain: 'testDomain.com' }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerDomains',
          query: { domains: ['testDomain.com'], isPrimary: true }
        })
        done()
      })
    })
    it('returns an array', done => {
      network.retrieveData.mockImplementation(() => Promise.resolve([data]))
      checkDomains({ domain: 'testDomain.com' }, (error, result) => {
        expect(result).toEqual([new Domain(data)])
        done()
      })
    })
  })

  describe('insertDomain', () => {
    let data
    beforeAll(() => {
      data = {
        assetManagerId: 1,
        domain: 'testDomain.com',
        isPrimary: true
      }
      network.insertData.mockImplementation(() => Promise.resolve(data))
    })
    test('with promise', () => {
      let promise = insertDomain({ AMId: 1, domain: data })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls insertData with correct params', done => {
      insertDomain({ domain: data }, (error, result) => {
        expect(network.insertData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerDomains',
          AMId: 1,
          data
        })
        done()
      })
    })
  })

  describe('retrieveEODBooks', () => {
    const mockedEODBook = {
      assetManagerId: 1,
      utcCloseTime: '18:00:00',
      bookId: 'testID',
      eodBookStatus: 'testStatus'
    }
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve(mockedEODBook)
      )
    })
    it('returns promise', () => {
      let promise = retrieveEODBooks({ AMId: 1, bookID: 'ABC' })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveEODBooks with the correct params', done => {
      retrieveEODBooks({ AMId: 1, bookID: 'ABC' }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerEODBooks',
          AMId: 1,
          bookID: 'ABC'
        })
        done()
      })
    })
    it('calls retrieveEODBooks with the correct params', done => {
      retrieveEODBooks({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerEODBooks',
          AMId: 1
        })
        done()
      })
    })
  })

  describe('getCredentialsForPubSub', () => {
    const mockedCredentials = {
      credentials: {
        AccessKeyId: 'testAcccessKey',
        SecretAccessKey: 'testSecretKey',
        SessionToken: 'testSessionToken'
      },
      topics: ['topic1', 'topic2']
    }
    beforeAll(() => {
      network.retrieveData.mockImplementation(() =>
        Promise.resolve(mockedCredentials)
      )
    })
    it('returns promise', () => {
      let promise = getCredentialsForPubSub({ AMId: 1 })
      expect(promise).toBeInstanceOf(Promise)
    })
    it('calls retrieveData with the correct params', done => {
      getCredentialsForPubSub({ AMId: 1 }, (error, result) => {
        expect(network.retrieveData).toHaveBeenCalledWith({
          AMaaSClass: 'assetManagerPubSubCredentials',
          AMId: 1,
          query: {}
        })
        done()
      })
    })
  })
})
<|endoftext|>


<commit_before>_.mapObject = function (obj, func) {
  var newObject = {};
  for (var index in obj) {
    newObject[index] = func(obj[index], index, obj);
  }
  return newObject;
};

Expression2Insert = function(gene, sampleLabels, expressionStrings) {
  // do some checks
  if (sampleLabels.length !== expressionStrings.length) {
    throw "Internal error: sampleLabels not the same length as " +
        " expressionStrings!";
  }

  var setObject = {};
  for (var index in sampleLabels) {
    var value = expressionStrings[index];
    var normalization = this.wranglerFile.options.normalization;
    var exceptNormalization = "samples." + sampleLabels[index] + ".";
    var parsedValue = parseFloat(value);
    setObject[exceptNormalization + normalization] = parsedValue;

    if (normalization === 'quantile_counts') {
      var log2Value = Math.log(parsedValue) / Math.LN2;
      setObject[exceptNormalization + 'rsem_quan_log2'] = log2Value;
    }
  }
  Expression2.upsert({
    gene: gene,
    Study_ID: this.submission.options.study_label,
    Collaborations: [this.submission.options.collaboration_label],
  }, {
    $set: setObject
  });
};

getNormalizationLabel = function (slug) {
  return GeneExpression.simpleSchema().schema()['values.' + slug].label;
};

validateNumberStrings = function (strings) {
  for (var index in strings) {
    var valueString = strings[index];
    if (isNaN(valueString)) {
      throw "Non-numerical expression value: " + valueString;
    }
  }
};
<commit_msg>log2 -Infinity expression2 bugfix<commit_after>_.mapObject = function (obj, func) {
  var newObject = {};
  for (var index in obj) {
    newObject[index] = func(obj[index], index, obj);
  }
  return newObject;
};

Expression2Insert = function(gene, sampleLabels, expressionStrings) {
  // do some checks
  if (sampleLabels.length !== expressionStrings.length) {
    throw "Internal error: sampleLabels not the same length as " +
        " expressionStrings!";
  }

  var setObject = {};
  for (var index in sampleLabels) {
    var value = expressionStrings[index];
    var normalization = this.wranglerFile.options.normalization;
    var exceptNormalization = "samples." + sampleLabels[index] + ".";
    var parsedValue = parseFloat(value);
    setObject[exceptNormalization + normalization] = parsedValue;

    if (normalization === 'quantile_counts') {
      var log2Value = Math.log(parsedValue + 1) / Math.LN2;
      setObject[exceptNormalization + 'rsem_quan_log2'] = log2Value;
    }
  }
  Expression2.upsert({
    gene: gene,
    Study_ID: this.submission.options.study_label,
    Collaborations: [this.submission.options.collaboration_label],
  }, {
    $set: setObject
  });
};

getNormalizationLabel = function (slug) {
  return GeneExpression.simpleSchema().schema()['values.' + slug].label;
};

validateNumberStrings = function (strings) {
  for (var index in strings) {
    var valueString = strings[index];
    if (isNaN(valueString)) {
      throw "Non-numerical expression value: " + valueString;
    }
  }
};
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'build.js'
    },
    devServer: {
        historyApiFallback: true,
        overlay: true
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
	},
	module: {
		rules: [
			{
				test: /\.css$/,
				use: [
					'vue-style-loader',
					'css-loader'
				]
			},
			{
				test: /\.scss$/,
				use: [
					'vue-style-loader',
					'css-loader',
					'sass-loader'
				]
			},
			{
				test: /\.sass/,
				use: [
					'vue-style-loader',
					'css-loader',
					'sass-loader?indentedSyntax'
				]
			},
			{
				test: /\.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/
			},
			{
				test: /\.(png|jpg|gif|svg)/,
				loader: 'file-loader',
				options: {
					name: '[name].[ext]?[hash]'
				}
			},
			{
				test: /\.vue$/,
				loader: 'vue-loader',
				options: {
					loaders: {
						'scss': [
							'vue-style-loader',
							'css-loader',
							'sass-loader'
						],
						'sass': [
							'vue-style-loader',
							'css-loader',
							'sass-loader'
						]
					}
				}
			}
		]
	},
	plugins: [
		new VueLoaderPlugin()
	]
};<commit_msg>modify config<commit_after>const path = require('path');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
	entry: './src/main.js',
	devtool: '#eval-source-map',
	output: {
		path: path.resolve(__dirname, './dist'),
		publicPath: '/dist/',
		filename: 'build.js'
	},
	devServer: {
		host: '192.168.0.104',   	// 服务器的IP地址，可以使用IP也可以使用localhost
		port: 8080,           		// 端口, 默认为8080
		historyApiFallback: true,
		overlay: true
	},
	resolve: {
		alias: {
			'vue$': 'vue/dist/vue.esm.js'
		}
	},
	module: {
		rules: [
			{
				test: /\.css$/,
				use: [
					'vue-style-loader',
					'css-loader'
				]
			},
			{
				test: /\.scss$/,
				use: [
					'vue-style-loader',
					'css-loader',
					'sass-loader'
				]
			},
			{
				test: /\.sass/,
				use: [
					'vue-style-loader',
					'css-loader',
					'sass-loader?indentedSyntax'
				]
			},
			{
				test: /\.js$/,
				loader: 'babel-loader',
				exclude: /node_modules/
			},
			{
				test: /\.(png|jpg|gif|svg)/,
				loader: 'file-loader',
				options: {
					name: '[name].[ext]?[hash]'
				}
			},
			{
				test: /\.vue$/,
				loader: 'vue-loader',
				options: {
					loaders: {
						'scss': [
							'vue-style-loader',
							'css-loader',
							'sass-loader'
						],
						'sass': [
							'vue-style-loader',
							'css-loader',
							'sass-loader'
						]
					}
				}
			}
		]
	},
	plugins: [
		new VueLoaderPlugin()
	]
};

if (process.env.NODE_ENV === 'production') {
	module.exports.devtool = '#source-map';
	module.exports.plugins = (module.exports.plugins || []).concat([
		new webpack.DefinePlugin({
			'process.env': {
				NODE_ENV: '"production"'
			}
		}),
		new webpack.optimize.UglifyJsPlugin({
			compress: {
				warnings: false
			}
		}),
	])
}<|endoftext|>


<commit_before>var _ = require('lodash');
var inflector = require('inflected');
var slug = require('slug');
var geo = require('./geo');

inflector.transliterations('de', function(t) {
  t.approximate('ü', 'ue');
  t.approximate('ö', 'oe');
  t.approximate('ä', 'ae');
  t.approximate('ß', 'ss');
});

function transliterateGerman(text) {
  return inflector.transliterate(text, {locale: 'de', replacement: ' '});
}

function normalizeId(input) {
  return slug(transliterateGerman(input)).toLowerCase();
}

function normalizeZhGeoName(input) {
  return input
    .replace(/Kreis (\d+)\+(\d+)/, function(match, kr1, kr2) { return 'Kreis ' + kr1 + ' und ' + kr2; })
    .replace(/ \(?ZH\)?\s*$/, '')
    .replace('a.d.', ' an der ')
    .replace('W\'thur', 'Winterthur')
    .replace('O\'Winterthur', 'Oberwinterthur')
    .replace(/ bei [^ ]+$/, '')
    .replace(/\s+/g, ' ');
}

function normalizeNum(input) {
  input = input.replace(/^\s+|\s+$/g, '');
  return input === '' ? undefined : +input;
}

module.exports.normalizeZhGeoName = normalizeZhGeoName;
module.exports.normalizeId = normalizeId;

var rr = {
  candidateId: normalizeId,
  kandkanton: function(rows) {
    var candidates = rows.map(function(row) {
      var candidate = {
        id: rr.candidateId(row.Name),
        type: 'candidate',
        name: row.Name,
        party: row.Partei,
        incumbent: row.Bisher === 'bisher',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        majority: normalizeNum(row['abs. Mehr']),
        votes: normalizeNum(row.Stimmen),
        elected: row.classes.indexOf('gewaehlt') !== -1
      };
      candidate.hasMajority = candidate.majority <= candidate.votes;
      return candidate;
    });

    return candidates;
  },
  kandgemeinden: function(rows) {
    var results = [];

    var geoIndex = geo.index();
    rows.forEach(function(row) {
      var name = normalizeZhGeoName(row.area.text);
      var area = geoIndex[normalizeId(name)];
      if(!area) {
        console.warn('unrecognised area', name, row);
        return;
      }
      _.each(_.omit(row, 'area'), function(value, name) {
        results.push({
          id: rr.candidateId(name),
          type: 'candidate',
          name: name,
          geography: {
            id: area.bfsk,
            type: 'area'
          },
          votes: normalizeNum(value.text),
          majority: value.classes.indexOf('cellquorum') !== -1
        });
      });
    });

    return results;
  }
};
module.exports.rr = rr;

var kr = {
  kand_kanton: function(rows) {
    var candidates = rows.map(function(row) {
      var candidate = {
        id: [row.Wk, row.Nr].join('-'),
        type: 'candidate',
        name: [row.Vorname, row.Name].join(' '),
        party: row['Listenbez.'],
        incumbent: row.Bisher === 'bisher',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        votes: normalizeNum(row.Stimmen),
        elected: row['Gew./Abg.'] === 'gewählt'
      };
      return candidate;
    });

    return candidates;
  },
  listen_kanton: function(rows) {
    var lists = rows.map(function(row) {
      var list = {
        id: row['Listen Bez.'],
        type: 'list',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        votes: normalizeNum(row.Stimmen),
        voters: normalizeNum(row['Wählerzahl']),
        percent: normalizeNum(row['Wähleranteil %']),
        seats: normalizeNum(row['Anzahl Sitze'])
      };
      return list;
    });

    return lists;
  },
  listen_vergleich_kanton: function(rows, year, previousYear) {
    var lists = rows.map(function(row) {
      var list = {
        id: row['Listen-Bezeichnung'].text,
        type: 'list',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        percent: normalizeNum(row['% Wähleranteil ' + year].text),
        previousPercent: normalizeNum(row['% Wähleranteil ' + previousYear].text),
        seats: normalizeNum(row['Sitze ' + year].text),
        previousSeats: normalizeNum(row['Sitze ' + previousYear].text)
      };
      return list;
    });

    return lists;
  },
  listen_wk_a: function(rows) {
    var results = [];

    rows.forEach(function(row, i) {
      var geography = {
        id: i + 1,
        type: 'constituency'
      }

      var lists = _.omit(_.omit(row, 'classes'), function(value, key) {
        return !!key.match(/^Wahlkreis und Auszählstand/);
      });

      var keys = {};
      row['Wahlkreis und Auszählstand 3'].split("\n").forEach(function(key, i) {
        keys[key] = i;
      });
      _.each(lists, function(values, id) {
        values = values.split("\n");
        results.push({
          id: id,
          type: 'list',
          geography: geography,
          votes: normalizeNum(values[keys['Stimmen absolut']]),
          voters: normalizeNum(values[keys['Wählerzahl']]),
          percent: normalizeNum(values[keys['Stimmen %']])
        });
      });
    });

    return results;
  }
}
module.exports.kr = kr;

<commit_msg>fix bug in number normalizer (handling undefined)<commit_after>var _ = require('lodash');
var inflector = require('inflected');
var slug = require('slug');
var geo = require('./geo');

inflector.transliterations('de', function(t) {
  t.approximate('ü', 'ue');
  t.approximate('ö', 'oe');
  t.approximate('ä', 'ae');
  t.approximate('ß', 'ss');
});

function transliterateGerman(text) {
  return inflector.transliterate(text, {locale: 'de', replacement: ' '});
}

function normalizeId(input) {
  return slug(transliterateGerman(input)).toLowerCase();
}

function normalizeZhGeoName(input) {
  return input
    .replace(/Kreis (\d+)\+(\d+)/, function(match, kr1, kr2) { return 'Kreis ' + kr1 + ' und ' + kr2; })
    .replace(/ \(?ZH\)?\s*$/, '')
    .replace('a.d.', ' an der ')
    .replace('W\'thur', 'Winterthur')
    .replace('O\'Winterthur', 'Oberwinterthur')
    .replace(/ bei [^ ]+$/, '')
    .replace(/\s+/g, ' ');
}

function normalizeNum(input) {
  input = (input || '').replace(/^\s+|\s+$/g, '');
  return input === '' ? undefined : +input;
}

module.exports.normalizeZhGeoName = normalizeZhGeoName;
module.exports.normalizeId = normalizeId;

var rr = {
  candidateId: normalizeId,
  kandkanton: function(rows) {
    var candidates = rows.map(function(row) {
      var candidate = {
        id: rr.candidateId(row.Name),
        type: 'candidate',
        name: row.Name,
        party: row.Partei,
        incumbent: row.Bisher === 'bisher',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        majority: normalizeNum(row['abs. Mehr']),
        votes: normalizeNum(row.Stimmen),
        elected: row.classes.indexOf('gewaehlt') !== -1
      };
      candidate.hasMajority = candidate.majority <= candidate.votes;
      return candidate;
    });

    return candidates;
  },
  kandgemeinden: function(rows) {
    var results = [];

    var geoIndex = geo.index();
    rows.forEach(function(row) {
      var name = normalizeZhGeoName(row.area.text);
      var area = geoIndex[normalizeId(name)];
      if(!area) {
        console.warn('unrecognised area', name, row);
        return;
      }
      _.each(_.omit(row, 'area'), function(value, name) {
        results.push({
          id: rr.candidateId(name),
          type: 'candidate',
          name: name,
          geography: {
            id: area.bfsk,
            type: 'area'
          },
          votes: normalizeNum(value.text),
          majority: value.classes.indexOf('cellquorum') !== -1
        });
      });
    });

    return results;
  }
};
module.exports.rr = rr;

var kr = {
  kand_kanton: function(rows) {
    var candidates = rows.map(function(row) {
      var candidate = {
        id: [row.Wk, row.Nr].join('-'),
        type: 'candidate',
        name: [row.Vorname, row.Name].join(' '),
        party: row['Listenbez.'],
        incumbent: row.Bisher === 'bisher',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        votes: normalizeNum(row.Stimmen),
        elected: row['Gew./Abg.'] === 'gewählt'
      };
      return candidate;
    });

    return candidates;
  },
  listen_kanton: function(rows) {
    var lists = rows.map(function(row) {
      var list = {
        id: row['Listen Bez.'],
        type: 'list',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        votes: normalizeNum(row.Stimmen),
        voters: normalizeNum(row['Wählerzahl']),
        percent: normalizeNum(row['Wähleranteil %']),
        seats: normalizeNum(row['Anzahl Sitze'])
      };
      return list;
    });

    return lists;
  },
  listen_vergleich_kanton: function(rows, year, previousYear) {
    var lists = rows.map(function(row) {
      var list = {
        id: row['Listen-Bezeichnung'].text,
        type: 'list',
        geography: {
          id: 'zh',
          type: 'canton'
        },
        percent: normalizeNum(row['% Wähleranteil ' + year].text),
        previousPercent: normalizeNum(row['% Wähleranteil ' + previousYear].text),
        seats: normalizeNum(row['Sitze ' + year].text),
        previousSeats: normalizeNum(row['Sitze ' + previousYear].text)
      };
      return list;
    });

    return lists;
  },
  listen_wk_a: function(rows) {
    var results = [];

    rows.forEach(function(row, i) {
      var geography = {
        id: i + 1,
        type: 'constituency'
      }

      var lists = _.omit(_.omit(row, 'classes'), function(value, key) {
        return !!key.match(/^Wahlkreis und Auszählstand/);
      });

      var keys = {};
      row['Wahlkreis und Auszählstand 3'].split("\n").forEach(function(key, i) {
        keys[key] = i;
      });
      _.each(lists, function(values, id) {
        values = values.split("\n");
        results.push({
          id: id,
          type: 'list',
          geography: geography,
          votes: normalizeNum(values[keys['Stimmen absolut']]),
          voters: normalizeNum(values[keys['Wählerzahl']]),
          percent: normalizeNum(values[keys['Stimmen %']])
        });
      });
    });

    return results;
  }
}
module.exports.kr = kr;

<|endoftext|>


<commit_before><commit_msg>Create jquery.tinyMap-2.4.1.js<commit_after><|endoftext|>


<commit_before><commit_msg>fixed error. forgot getShape function.  half of video 21 coded and commented<commit_after><|endoftext|>


<commit_before>/* @flow */

'use strict';

const EventEmitter = require('cannery-event-emitter');
const BaseType = require('./base');
const ObjectType = require('./object');
const validate = require('valid-point');

class ArrayType extends EventEmitter {

    constructor (parentModel: Object, ArrayType: Function = BaseType, arrayFields: Object, options: Object = {}) {
        super();

        this._parent = parentModel;
        this.options = options;
        this.Type = ArrayType;
        this._typedArray = [];
        this._fields = arrayFields;
        this._typeOptions = this.options;
        this.validations = this.options.validations;

        if (parentModel && parentModel.emit) {
            this.on('*', function () {
                parentModel.emit(...arguments);
            });
        }
    }

    _userChange (array: Array<any>): Object {
        this.set(array);

        this.emit('userChange');
        this.emit('change');

        return this;
    }

    add (item: any, index: number): Object {
        let array = this._clone();
        const typedItem = this.instantiateItem(item);

        typedItem.apply(item);

        if (typeof index !== 'number') {
            index = array.length;
        }

        array.splice(index, 0, typedItem);

        return this._userChange(array);
    }

    all (): Array<any> {
        const arr = this._typedArray.map((item) => {

            // Object
            if (item instanceof ObjectType) {
                return item;
            }

            return item.get();
        });

        return arr;
    }

    apply (data: Array<any>): Object {

        const array = data.map((item) => {

            const typedItem = this.instantiateItem(item);

            typedItem.apply(item);

            return typedItem;

        });

        this.set(array);

        return this;
    }

    forEach (callback: Function): void {
        return this.all().forEach(callback);
    }

    get (index: number): any {
        return this.all()[index];
    }

    instantiateItem (): Object {
        return new this.Type(Object.assign({}, this._fields), Object.assign({}, this._typeOptions));
    }

    length (): number {
        return this.all().length;
    }

    map (callback: Function): Array<any> {
        return this.all().map(callback);
    }

    move (oldIndex: number, newIndex: number): Object {
        let array = this._clone();
        const item = array[oldIndex];

        array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);

        return this._userChange(array);
    }

    remove (index: number): Object {
        let array = this._clone();

        array.splice(index, 1);

        return this._userChange(array);
    }

    removeAll (): Object {
        return this._userChange([]);
    }

    _clone (): Array<Object> {
        return this._typedArray.slice(0);
    }

    set (arr: Array<any>) {
        this._typedArray = arr;
        this.emit('change');
    }

    toJSON (): Array<any> {
        return this.all();
    }

}

module.exports = ArrayType;
<commit_msg>return on a null value provided to Array.apply()<commit_after>/* @flow */

'use strict';

const EventEmitter = require('cannery-event-emitter');
const BaseType = require('./base');
const ObjectType = require('./object');
const validate = require('valid-point');

class ArrayType extends EventEmitter {

    constructor (parentModel: Object, ArrayType: Function = BaseType, arrayFields: Object, options: Object = {}) {
        super();

        this._parent = parentModel;
        this.options = options;
        this.Type = ArrayType;
        this._typedArray = [];
        this._fields = arrayFields;
        this._typeOptions = this.options;
        this.validations = this.options.validations;

        if (parentModel && parentModel.emit) {
            this.on('*', function () {
                parentModel.emit(...arguments);
            });
        }
    }

    _userChange (array: Array<any>): Object {
        this.set(array);

        this.emit('userChange');
        this.emit('change');

        return this;
    }

    add (item: any, index: number): Object {
        let array = this._clone();
        const typedItem = this.instantiateItem(item);

        typedItem.apply(item);

        if (typeof index !== 'number') {
            index = array.length;
        }

        array.splice(index, 0, typedItem);

        return this._userChange(array);
    }

    all (): Array<any> {
        const arr = this._typedArray.map((item) => {

            // Object
            if (item instanceof ObjectType) {
                return item;
            }

            return item.get();
        });

        return arr;
    }

    apply (data: ?Array<any>): Object {

        if (!data) {
            return;
        }

        const array = data.map((item) => {

            const typedItem = this.instantiateItem(item);

            typedItem.apply(item);

            return typedItem;

        });

        this.set(array);

        return this;
    }

    forEach (callback: Function): void {
        return this.all().forEach(callback);
    }

    get (index: number): any {
        return this.all()[index];
    }

    instantiateItem (): Object {
        return new this.Type(Object.assign({}, this._fields), Object.assign({}, this._typeOptions));
    }

    length (): number {
        return this.all().length;
    }

    map (callback: Function): Array<any> {
        return this.all().map(callback);
    }

    move (oldIndex: number, newIndex: number): Object {
        let array = this._clone();
        const item = array[oldIndex];

        array.splice(newIndex, 0, array.splice(oldIndex, 1)[0]);

        return this._userChange(array);
    }

    remove (index: number): Object {
        let array = this._clone();

        array.splice(index, 1);

        return this._userChange(array);
    }

    removeAll (): Object {
        return this._userChange([]);
    }

    _clone (): Array<Object> {
        return this._typedArray.slice(0);
    }

    set (arr: Array<any>) {
        this._typedArray = arr;
        this.emit('change');
    }

    toJSON (): Array<any> {
        return this.all();
    }

}

module.exports = ArrayType;
<|endoftext|>


<commit_before>/**
 * @fileOverview DOM events for ns.View
 */

/**
 * Хеш событий для удобного биндинга touch/desktop
 * @type {Object}
 */
ns.V.EVENTS = {
    'click': 'click',
    'dblclick': 'dblclick',
    'mousedown': 'mousedown',
    'mousemove': 'mousemove',
    'mouseup': 'mouseup'
};

/**
 * Список DOM-событий.
 * @type {Array}
 * @constant
 */
ns.V.DOM_EVENTS = [
    'blur',
    'change',
    'click',
    'dblclick',
    'dragstart',
    'dragenter',
    'dragover',
    'dragleave',
    'drag',
    'drop',
    'dragend',
    'focus',
    'focusin',
    'focusout',
    'keydown',
    'keypress',
    'keyup',
    'mousedown',
    'mouseenter',
    'mouseleave',
    'mousemove',
    'mouseout',
    'mouseover',
    'mouseup',
    'resize',
    'scroll',
    'submit'
];

/**
 * Список внутренних Noscript-событий.
 * @type {Array}
 * @constant
 */
ns.V.NS_EVENTS = [
    'ns-async',
    'ns-init',
    'ns-htmlinit',
    'ns-show',
    'ns-repaint',
    'ns-hide',
    'ns-htmldestroy'
];

//TODO: Pointer events support (MSIE 10)

// @see http://sitr.us/2011/07/28/how-mobile-safari-emulates-mouse-events.html
// @see http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
if (ns.IS_TOUCH) {
    ns.V.DOM_EVENTS.push('tap', 'touchstart', 'touchmove', 'touchend');
    ns.V.EVENTS = {
        'click': 'tap',
        'dblclick': 'doubletap',
        'mousedown': 'touchstart',
        'mousemove': 'touchmove',
        'mouseup': 'touchend'
    };

}
<commit_msg>add swipe events<commit_after>/**
 * @fileOverview DOM events for ns.View
 */

/**
 * Хеш событий для удобного биндинга touch/desktop
 * @type {Object}
 */
ns.V.EVENTS = {
    'click': 'click',
    'dblclick': 'dblclick',
    'mousedown': 'mousedown',
    'mousemove': 'mousemove',
    'mouseup': 'mouseup'
};

/**
 * Список DOM-событий.
 * @type {Array}
 * @constant
 */
ns.V.DOM_EVENTS = [
    'blur',
    'change',
    'click',
    'dblclick',
    'dragstart',
    'dragenter',
    'dragover',
    'dragleave',
    'drag',
    'drop',
    'dragend',
    'focus',
    'focusin',
    'focusout',
    'keydown',
    'keypress',
    'keyup',
    'mousedown',
    'mouseenter',
    'mouseleave',
    'mousemove',
    'mouseout',
    'mouseover',
    'mouseup',
    'resize',
    'scroll',
    'submit'
];

/**
 * Список внутренних Noscript-событий.
 * @type {Array}
 * @constant
 */
ns.V.NS_EVENTS = [
    'ns-async',
    'ns-init',
    'ns-htmlinit',
    'ns-show',
    'ns-repaint',
    'ns-hide',
    'ns-htmldestroy'
];

//TODO: Pointer events support (MSIE 10)

// @see http://sitr.us/2011/07/28/how-mobile-safari-emulates-mouse-events.html
// @see http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
if (ns.IS_TOUCH) {
    ns.V.DOM_EVENTS.push(
        'swipe',
        'swipeleft',
        'swiperight',
        'tap',
        'touchstart',
        'touchmove',
        'touchend'
    );
    ns.V.EVENTS = {
        'click': 'tap',
        'dblclick': 'doubletap',
        'mousedown': 'touchstart',
        'mousemove': 'touchmove',
        'mouseup': 'touchend'
    };

}
<|endoftext|>


<commit_before>goog.provide('og.webgl.Handler');

goog.require('og.webgl');
goog.require('og.math');
goog.require('og.webgl.ShaderController');
goog.require('og.ImageCanvas');

/**
 * A WebGL handler for accessing low-level WebGL capabilities.
 * @class
 * @param {string} id - Canvas element id that WebGL handler assings with. If it's null or undefined creates
 * hidden canvas and handler bacomes hidden.
 * @param {Object} [param] - Handler options:
 * @param {number} [param.anisotropy] - Anisitropy filter degree. 8 is default.
 * @param {number} [param.width] - Hidden handler width. 256 is default.
 * @param {number} [param.height] - Hidden handler height. 256 is default.
 * @param {Object} [param.context] - Native WebGL context attributes. See https://www.khronos.org/registry/webgl/specs/latest/1.0/#WEBGLCONTEXTATTRIBUTES
 * @param {Array.<string>} [param.extensions] - Additional WebGL extension list. Available by default: OES_standard_derivatives, EXT_texture_filter_anisotropic.
 */
og.webgl.Handler = function (id, params) {

    this.backgroundColor = { "r": 0.41, "g": 0.41, "b": 0.41 };

    this.fps = 0;
    this.delta = 0;
    this.animationSpeed = 1.0;

    this.canvas = null;
    this.gl = null;
    this.shaderPrograms = {};
    this.activeShaderProgram = null;

    //set parameters
    this._params = params || {};
    this._params.anisotropy = this._params.anisotropy || 8;
    this._params.width = this._params.width || 256;
    this._params.height = this._params.height || 256;
    this._params.context = this._params.context || {};
    this._params.extensions = this._params.extensions || [];
    this._pExtensions = {};

    this._id = id;
    this._lastAnimationFrameTime = 0;
    this._initialized = false;

    this._frameCallback = function () { };
};

og.webgl.Handler.prototype.setFrameCallback = function (callback) {
    callback && (this._frameCallback = callback);
};

og.webgl.Handler.prototype.createTexture_n = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_l = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_mm = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_af = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameterf(gl.TEXTURE_2D, this._pExtensions.EXT_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT, this._params.anisotropy);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture = og.webgl.Handler.prototype.createTexture_af;

og.webgl.Handler.prototype.loadCubeMapTexture = function (params) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    var faces = [[params.px, gl.TEXTURE_CUBE_MAP_POSITIVE_X],
                 [params.nx, gl.TEXTURE_CUBE_MAP_NEGATIVE_X],
                 [params.py, gl.TEXTURE_CUBE_MAP_POSITIVE_Y],
                 [params.ny, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y],
                 [params.pz, gl.TEXTURE_CUBE_MAP_POSITIVE_Z],
                 [params.nz, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]];

    var imageCanvas = new og.ImageCanvas();
    imageCanvas.fillEmpty();
    var emptyImage = imageCanvas.getImage();

    for (var i = 0; i < faces.length; i++) {
        var face = faces[i][1];
        gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
        gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);
    }

    for (var i = 0; i < faces.length; i++) {
        var face = faces[i][1];
        var image = new Image();
        image.crossOrigin = '';
        image.onload = function (texture, face, image) {
            return function () {
                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
                gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            }
        }(texture, face, image);
        image.src = faces[i][0];
    }
    return texture;
};

og.webgl.Handler.prototype.addShaderProgram = function (program, notActivate) {
    if (!this.shaderPrograms[program.name]) {
        var sc = new og.webgl.ShaderController(this, program);
        this.shaderPrograms[program.name] = sc;
        this._initShaderController(sc);
        if (notActivate)
            sc._activated = false;
    } else {
        alert(program.name + " is allready exists.");
    }
};

og.webgl.Handler.prototype._initShaderController = function (sc) {
    if (this._initialized) {
        sc.initialize();
        if (!this.activeShaderProgram) {
            this.activeShaderProgram = sc;
            sc.activate();
        } else {
            sc.deactivate();
            this.activeShaderProgram._program.enableAttribArrays();
            this.activeShaderProgram._program.use();
        }
    }
};

og.webgl.Handler.prototype.addShaderPrograms = function (programsArr) {
    for (var i = 0; i < programsArr.length; i++) {
        this.addShaderProgram(programsArr[i]);
    }
};

og.webgl.Handler.prototype._initShaderPrograms = function () {
    for (var p in this.shaderPrograms) {
        this._initShaderController(this.shaderPrograms[p]);
    }
};

og.webgl.Handler.prototype.initExtension = function (extensionStr) {
    if (!(this._pExtensions && this._pExtensions[extensionStr]))
        this._pExtensions[extensionStr] = og.webgl.getExtension(this.gl, extensionStr);
};

og.webgl.Handler.prototype.init = function () {

    if (this._id) {
        this.canvas = document.getElementById(this._id);
    } else {
        this.canvas = document.createElement("canvas");
        this.canvas.width = this._params.width;
        this.canvas.height = this._params.height;
    }

    this.gl = og.webgl.initWebGLContext(this.canvas, this._params.context);
    this._initialized = true;

    /** Sets deafult extensions */
    this._params.extensions.push("OES_standard_derivatives");
    this._params.extensions.push("EXT_texture_filter_anisotropic");

    var i = this._params.extensions.length;
    while (i--) {
        this.initExtension(this._params.extensions[i]);
    }

    if (!this._pExtensions.EXT_texture_filter_anisotropic)
        this.createTexture = this.createTexture_mm;

    /** Initilalize shaders and rendering parameters*/
    this._initShaderPrograms();
    this._setDefaults();
};

og.webgl.Handler.prototype._setDefaults = function () {
    this.activateDepthTest();
    this.setSize(this.canvas.width, this.canvas.height);
    this.gl.frontFace(this.gl.CCW);
    this.gl.cullFace(this.gl.BACK);
    this.activateFaceCulling();
    this.deactivateBlending();
};

og.webgl.Handler.prototype.activateDepthTest = function () {
    this.gl.enable(this.gl.DEPTH_TEST);
};

og.webgl.Handler.prototype.deactivateDepthTest = function () {
    this.gl.disable(this.gl.DEPTH_TEST);
};

og.webgl.Handler.prototype.activateFaceCulling = function () {
    this.gl.enable(this.gl.CULL_FACE);
};

og.webgl.Handler.prototype.deactivateFaceCulling = function () {
    this.gl.disable(this.gl.CULL_FACE);
};

og.webgl.Handler.prototype.activateBlending = function () {
    this.gl.enable(this.gl.BLEND);
};

og.webgl.Handler.prototype.deactivateBlending = function () {
    this.gl.disable(this.gl.BLEND);
};

og.webgl.Handler.prototype.createArrayBuffer = function (array, itemSize, numItems) {
    var buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
    this.gl.bufferData(this.gl.ARRAY_BUFFER, array, this.gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = numItems;
    return buffer;
};

og.webgl.Handler.prototype.createElementArrayBuffer = function (array, itemSize, numItems) {
    var buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, buffer);
    this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, array, this.gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = numItems;
    return buffer;
};

og.webgl.Handler.prototype.setSize = function (width, height) {
    var w = width, h = Math.max(1, height);
    this.canvas.width = w;
    this.canvas.height = h;
    this.canvas.aspect = w / h;
    this.canvas._oneByHeight = 1 / h;
    if (this.gl) {
        this.gl.viewport(0, 0, w, h);
    }
};

og.webgl.Handler.prototype.drawFrame = function (now) {

    /** Canvas resize checking */
    var canvas = this.canvas;
    if (canvas.clientWidth != canvas.width ||
        canvas.clientHeight != canvas.height) {
        this.setSize(canvas.clientWidth, canvas.clientHeight);
        this.onCanvasResize(canvas);
    }

    /** Calculate FPS */
    this.fps = 1000.0 / (now - this._lastAnimationFrameTime);
    this._lastAnimationFrameTime = now;
    this.delta = this.animationSpeed / this.fps;

    /** Draw frame */
    this._frameCallback();
};

og.webgl.Handler.prototype.clearFrame = function () {
    var gl = this.gl;
    var bc = this.backgroundColor;
    this.gl.clearColor(bc.r, bc.g, bc.b, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
};

og.webgl.Handler.prototype.start = function () {
    this._animationFrameCallback(new Date().getTime());
};

og.webgl.Handler.prototype._animationFrameCallback = function (now) {
    var that = this;
    window.requestAnimationFrame(function () {
        that.drawFrame(now);
        that._animationFrameCallback(new Date().getTime());
    });
};<commit_msg>Handler documentation almost ready.<commit_after>goog.provide('og.webgl.Handler');

goog.require('og.webgl');
goog.require('og.math');
goog.require('og.webgl.ShaderController');
goog.require('og.ImageCanvas');

/**
 * A WebGL handler for accessing low-level WebGL capabilities.
 * @class
 * @param {string} id - Canvas element id that WebGL handler assings with. If it's null or undefined creates
 * hidden canvas and handler bacomes hidden.
 * @param {Object} [param] - Handler options:
 * @param {number} [param.anisotropy] - Anisitropy filter degree. 8 is default.
 * @param {number} [param.width] - Hidden handler width. 256 is default.
 * @param {number} [param.height] - Hidden handler height. 256 is default.
 * @param {Object} [param.context] - Native WebGL context attributes. See https://www.khronos.org/registry/webgl/specs/latest/1.0/#WEBGLCONTEXTATTRIBUTES
 * @param {Array.<string>} [param.extensions] - Additional WebGL extension list. Available by default: OES_standard_derivatives, EXT_texture_filter_anisotropic.
 */
og.webgl.Handler = function (id, params) {

    /**
     * Frame background color.
     * @public
     * @type {Object}
     * @type {number} r - Red
     * @type {number} g - Green
     * @type {number} b - Blue
     */
    this.backgroundColor = { "r": 0.41, "g": 0.41, "b": 0.41 };

    /**
     * Calculated frame per second value.
     * @public
     * @readonly
     * @type {number}
     */
    this.fps = 0;

    /**
     * Calculated time synchronization value uses for the different fps time synchonization.
     * @public
     * @readonly
     * @type {number}
     */
    this.delta = 0;

    /**
     * Animation speed. 1.0 - by deafault. x1.0 means normal time speed.
     * @public
     * @type {number}
     */
    this.animationSpeed = 1.0;

    /**
     * WebGL rendering canvas element.
     * @public
     * @type {Object}
     */
    this.canvas = null;

    /**
     * WebGL context.
     * @public
     * @type {Object}
     */
    this.gl = null;

    /**
     * Shader program controller list.
     * @public
     * @type {Object.<og.webgl.ShaderController>}
     */
    this.shaderPrograms = {};

    /**
     * Current active shader program controller.
     * @public
     * @type {og.webgl.ShaderController}
     */
    this.activeShaderProgram = null;

    /**
     * @private
     * @type {Object}
     */
    this._params = params || {};
    this._params.anisotropy = this._params.anisotropy || 8;
    this._params.width = this._params.width || 256;
    this._params.height = this._params.height || 256;
    this._params.context = this._params.context || {};
    this._params.extensions = this._params.extensions || [];

    /**
     * @private
     * @type {Object}
     */
    this._pExtensions = {};

    this._id = id;
    this._lastAnimationFrameTime = 0;
    this._initialized = false;

    /**
     * Animation frame function assigned from outside(Ex. from Renderer).
     * @private
     * @type {frameCallback}
     */
    this._frameCallback = function () { };
};

og.webgl.Handler.prototype.setFrameCallback = function (callback) {
    callback && (this._frameCallback = callback);
};

og.webgl.Handler.prototype.createTexture_n = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_l = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, gl.LUMINANCE, gl.UNSIGNED_BYTE, image);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_mm = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture_af = function (image) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
    gl.texParameterf(gl.TEXTURE_2D, this._pExtensions.EXT_texture_filter_anisotropic.TEXTURE_MAX_ANISOTROPY_EXT, this._params.anisotropy);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

og.webgl.Handler.prototype.createTexture = og.webgl.Handler.prototype.createTexture_af;

og.webgl.Handler.prototype.loadCubeMapTexture = function (params) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

    var faces = [[params.px, gl.TEXTURE_CUBE_MAP_POSITIVE_X],
                 [params.nx, gl.TEXTURE_CUBE_MAP_NEGATIVE_X],
                 [params.py, gl.TEXTURE_CUBE_MAP_POSITIVE_Y],
                 [params.ny, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y],
                 [params.pz, gl.TEXTURE_CUBE_MAP_POSITIVE_Z],
                 [params.nz, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z]];

    var imageCanvas = new og.ImageCanvas();
    imageCanvas.fillEmpty();
    var emptyImage = imageCanvas.getImage();

    for (var i = 0; i < faces.length; i++) {
        var face = faces[i][1];
        gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
        gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, emptyImage);
    }

    for (var i = 0; i < faces.length; i++) {
        var face = faces[i][1];
        var image = new Image();
        image.crossOrigin = '';
        image.onload = function (texture, face, image) {
            return function () {
                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
                gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
                gl.texImage2D(face, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
            }
        }(texture, face, image);
        image.src = faces[i][0];
    }
    return texture;
};

og.webgl.Handler.prototype.addShaderProgram = function (program, notActivate) {
    if (!this.shaderPrograms[program.name]) {
        var sc = new og.webgl.ShaderController(this, program);
        this.shaderPrograms[program.name] = sc;
        this._initShaderController(sc);
        if (notActivate)
            sc._activated = false;
    } else {
        alert(program.name + " is allready exists.");
    }
};

og.webgl.Handler.prototype._initShaderController = function (sc) {
    if (this._initialized) {
        sc.initialize();
        if (!this.activeShaderProgram) {
            this.activeShaderProgram = sc;
            sc.activate();
        } else {
            sc.deactivate();
            this.activeShaderProgram._program.enableAttribArrays();
            this.activeShaderProgram._program.use();
        }
    }
};

og.webgl.Handler.prototype.addShaderPrograms = function (programsArr) {
    for (var i = 0; i < programsArr.length; i++) {
        this.addShaderProgram(programsArr[i]);
    }
};

og.webgl.Handler.prototype._initShaderPrograms = function () {
    for (var p in this.shaderPrograms) {
        this._initShaderController(this.shaderPrograms[p]);
    }
};

og.webgl.Handler.prototype.initExtension = function (extensionStr) {
    if (!(this._pExtensions && this._pExtensions[extensionStr]))
        this._pExtensions[extensionStr] = og.webgl.getExtension(this.gl, extensionStr);
};

og.webgl.Handler.prototype.init = function () {

    if (this._id) {
        this.canvas = document.getElementById(this._id);
    } else {
        this.canvas = document.createElement("canvas");
        this.canvas.width = this._params.width;
        this.canvas.height = this._params.height;
    }

    this.gl = og.webgl.initWebGLContext(this.canvas, this._params.context);
    this._initialized = true;

    /** Sets deafult extensions */
    this._params.extensions.push("OES_standard_derivatives");
    this._params.extensions.push("EXT_texture_filter_anisotropic");

    var i = this._params.extensions.length;
    while (i--) {
        this.initExtension(this._params.extensions[i]);
    }

    if (!this._pExtensions.EXT_texture_filter_anisotropic)
        this.createTexture = this.createTexture_mm;

    /** Initilalize shaders and rendering parameters*/
    this._initShaderPrograms();
    this._setDefaults();
};

og.webgl.Handler.prototype._setDefaults = function () {
    this.activateDepthTest();
    this.setSize(this.canvas.width, this.canvas.height);
    this.gl.frontFace(this.gl.CCW);
    this.gl.cullFace(this.gl.BACK);
    this.activateFaceCulling();
    this.deactivateBlending();
};

og.webgl.Handler.prototype.activateDepthTest = function () {
    this.gl.enable(this.gl.DEPTH_TEST);
};

og.webgl.Handler.prototype.deactivateDepthTest = function () {
    this.gl.disable(this.gl.DEPTH_TEST);
};

og.webgl.Handler.prototype.activateFaceCulling = function () {
    this.gl.enable(this.gl.CULL_FACE);
};

og.webgl.Handler.prototype.deactivateFaceCulling = function () {
    this.gl.disable(this.gl.CULL_FACE);
};

og.webgl.Handler.prototype.activateBlending = function () {
    this.gl.enable(this.gl.BLEND);
};

og.webgl.Handler.prototype.deactivateBlending = function () {
    this.gl.disable(this.gl.BLEND);
};

og.webgl.Handler.prototype.createArrayBuffer = function (array, itemSize, numItems) {
    var buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
    this.gl.bufferData(this.gl.ARRAY_BUFFER, array, this.gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = numItems;
    return buffer;
};

og.webgl.Handler.prototype.createElementArrayBuffer = function (array, itemSize, numItems) {
    var buffer = this.gl.createBuffer();
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, buffer);
    this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, array, this.gl.STATIC_DRAW);
    buffer.itemSize = itemSize;
    buffer.numItems = numItems;
    return buffer;
};

og.webgl.Handler.prototype.setSize = function (width, height) {
    var w = width, h = Math.max(1, height);
    this.canvas.width = w;
    this.canvas.height = h;
    this.canvas.aspect = w / h;
    this.canvas._oneByHeight = 1 / h;
    if (this.gl) {
        this.gl.viewport(0, 0, w, h);
    }
};

og.webgl.Handler.prototype.drawFrame = function (now) {

    /** Canvas resize checking */
    var canvas = this.canvas;
    if (canvas.clientWidth != canvas.width ||
        canvas.clientHeight != canvas.height) {
        this.setSize(canvas.clientWidth, canvas.clientHeight);
        this.onCanvasResize(canvas);
    }

    /** Calculate FPS */
    this.fps = 1000.0 / (now - this._lastAnimationFrameTime);
    this._lastAnimationFrameTime = now;
    this.delta = this.animationSpeed / this.fps;

    /** Draw frame */
    this._frameCallback();
};

og.webgl.Handler.prototype.clearFrame = function () {
    var gl = this.gl;
    var bc = this.backgroundColor;
    this.gl.clearColor(bc.r, bc.g, bc.b, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
};

og.webgl.Handler.prototype.start = function () {
    this._animationFrameCallback(new Date().getTime());
};

og.webgl.Handler.prototype._animationFrameCallback = function (now) {
    var that = this;
    window.requestAnimationFrame(function () {
        that.drawFrame(now);
        that._animationFrameCallback(new Date().getTime());
    });
};<|endoftext|>


<commit_before>/**
 * @module ol/featureloader
 */
import {VOID} from './functions.js';
import FormatType from './format/FormatType.js';

/**
 * {@link module:ol/source/Vector} sources use a function of this type to
 * load features.
 *
 * This function takes an {@link module:ol/extent~Extent} representing the area to be loaded,
 * a `{number}` representing the resolution (map units per pixel) and an
 * {@link module:ol/proj/Projection} for the projection  as
 * arguments. `this` within the function is bound to the
 * {@link module:ol/source/Vector} it's called from.
 *
 * The function is responsible for loading the features and adding them to the
 * source.
 * @typedef {function(this:import("./source/Vector.js").default, import("./extent.js").Extent, number,
 *                    import("./proj/Projection.js").default)} FeatureLoader
 * @api
 */

/**
 * {@link module:ol/source/Vector} sources use a function of this type to
 * get the url to load features from.
 *
 * This function takes an {@link module:ol/extent~Extent} representing the area
 * to be loaded, a `{number}` representing the resolution (map units per pixel)
 * and an {@link module:ol/proj/Projection} for the projection  as
 * arguments and returns a `{string}` representing the URL.
 * @typedef {function(import("./extent.js").Extent, number, import("./proj/Projection.js").default): string} FeatureUrlFunction
 * @api
 */

/**
 * @param {string|FeatureUrlFunction} url Feature URL service.
 * @param {import("./format/Feature.js").default} format Feature format.
 * @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:import("./source/Vector.js").default, Array<import("./Feature.js").default>)} success
 *     Function called with the loaded features and optionally with the data
 *     projection. Called with the vector tile or source as `this`.
 * @param {function(this:import("./VectorTile.js").default)|function(this:import("./source/Vector.js").default)} failure
 *     Function called when loading failed. Called with the vector tile or
 *     source as `this`.
 * @return {FeatureLoader} The feature loader.
 */
export function loadFeaturesXhr(url, format, success, failure) {
  return (
    /**
     * @param {import("./extent.js").Extent} extent Extent.
     * @param {number} resolution Resolution.
     * @param {import("./proj/Projection.js").default} projection Projection.
     * @this {import("./source/Vector.js").default|import("./VectorTile.js").default}
     */
    function(extent, resolution, projection) {
      const xhr = new XMLHttpRequest();
      xhr.open('GET',
        typeof url === 'function' ? url(extent, resolution, projection) : url,
        true);
      if (format.getType() == FormatType.ARRAY_BUFFER) {
        xhr.responseType = 'arraybuffer';
      }
      /**
       * @param {Event} event Event.
       * @private
       */
      xhr.onload = function(event) {
        // status will be 0 for file:// urls
        if (!xhr.status || xhr.status >= 200 && xhr.status < 300) {
          const type = format.getType();
          /** @type {Document|Node|Object|string|undefined} */
          let source;
          if (type == FormatType.JSON || type == FormatType.TEXT) {
            source = xhr.responseText;
          } else if (type == FormatType.XML) {
            source = xhr.responseXML;
            if (!source) {
              source = new DOMParser().parseFromString(xhr.responseText, 'application/xml');
            }
          } else if (type == FormatType.ARRAY_BUFFER) {
            source = /** @type {ArrayBuffer} */ (xhr.response);
          }
          if (source) {
            success.call(this, format.readFeatures(source,
              {featureProjection: projection}),
            format.readProjection(source), format.getLastExtent());
          } else {
            failure.call(this);
          }
        } else {
          failure.call(this);
        }
      }.bind(this);
      /**
       * @private
       */
      xhr.onerror = function() {
        failure.call(this);
      }.bind(this);
      xhr.send();
    }
  );
}

/**
 * Create an XHR feature loader for a `url` and `format`. The feature loader
 * loads features (with XHR), parses the features, and adds them to the
 * vector source.
 * @param {string|FeatureUrlFunction} url Feature URL service.
 * @param {import("./format/Feature.js").default} format Feature format.
 * @return {FeatureLoader} The feature loader.
 * @api
 */
export function xhr(url, format) {
  return loadFeaturesXhr(url, format,
    /**
     * @param {Array<import("./Feature.js").default>} features The loaded features.
     * @param {import("./proj/Projection.js").default} dataProjection Data
     * projection.
     * @this {import("./source/Vector.js").default}
     */
    function(features, dataProjection) {
      this.addFeatures(features);
    }, /* FIXME handle error */ VOID);
}
<commit_msg>Featureloader this reference can also be ol.VectorTile<commit_after>/**
 * @module ol/featureloader
 */
import {VOID} from './functions.js';
import FormatType from './format/FormatType.js';
import VectorSource from './source/Vector';

/**
 * {@link module:ol/source/Vector} sources use a function of this type to
 * load features.
 *
 * This function takes an {@link module:ol/extent~Extent} representing the area to be loaded,
 * a `{number}` representing the resolution (map units per pixel) and an
 * {@link module:ol/proj/Projection} for the projection  as
 * arguments. `this` within the function is bound to the
 * {@link module:ol/source/Vector} it's called from.
 *
 * The function is responsible for loading the features and adding them to the
 * source.
 * @typedef {function(this:(VectorSource|import("./VectorTile.js").default), import("./extent.js").Extent, number,
 *                    import("./proj/Projection.js").default)} FeatureLoader
 * @api
 */

/**
 * {@link module:ol/source/Vector} sources use a function of this type to
 * get the url to load features from.
 *
 * This function takes an {@link module:ol/extent~Extent} representing the area
 * to be loaded, a `{number}` representing the resolution (map units per pixel)
 * and an {@link module:ol/proj/Projection} for the projection  as
 * arguments and returns a `{string}` representing the URL.
 * @typedef {function(import("./extent.js").Extent, number, import("./proj/Projection.js").default): string} FeatureUrlFunction
 * @api
 */

/**
 * @param {string|FeatureUrlFunction} url Feature URL service.
 * @param {import("./format/Feature.js").default} format Feature format.
 * @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:VectorSource, Array<import("./Feature.js").default>)} success
 *     Function called with the loaded features and optionally with the data
 *     projection. Called with the vector tile or source as `this`.
 * @param {function(this:import("./VectorTile.js").default)|function(this:VectorSource)} failure
 *     Function called when loading failed. Called with the vector tile or
 *     source as `this`.
 * @return {FeatureLoader} The feature loader.
 */
export function loadFeaturesXhr(url, format, success, failure) {
  return (
    /**
     * @param {import("./extent.js").Extent} extent Extent.
     * @param {number} resolution Resolution.
     * @param {import("./proj/Projection.js").default} projection Projection.
     * @this {VectorSource|import("./VectorTile.js").default}
     */
    function(extent, resolution, projection) {
      const xhr = new XMLHttpRequest();
      xhr.open('GET',
        typeof url === 'function' ? url(extent, resolution, projection) : url,
        true);
      if (format.getType() == FormatType.ARRAY_BUFFER) {
        xhr.responseType = 'arraybuffer';
      }
      /**
       * @param {Event} event Event.
       * @private
       */
      xhr.onload = function(event) {
        // status will be 0 for file:// urls
        if (!xhr.status || xhr.status >= 200 && xhr.status < 300) {
          const type = format.getType();
          /** @type {Document|Node|Object|string|undefined} */
          let source;
          if (type == FormatType.JSON || type == FormatType.TEXT) {
            source = xhr.responseText;
          } else if (type == FormatType.XML) {
            source = xhr.responseXML;
            if (!source) {
              source = new DOMParser().parseFromString(xhr.responseText, 'application/xml');
            }
          } else if (type == FormatType.ARRAY_BUFFER) {
            source = /** @type {ArrayBuffer} */ (xhr.response);
          }
          if (source) {
            success.call(this, format.readFeatures(source,
              {featureProjection: projection}),
            format.readProjection(source), format.getLastExtent());
          } else {
            failure.call(this);
          }
        } else {
          failure.call(this);
        }
      }.bind(this);
      /**
       * @private
       */
      xhr.onerror = function() {
        failure.call(this);
      }.bind(this);
      xhr.send();
    }
  );
}

/**
 * Create an XHR feature loader for a `url` and `format`. The feature loader
 * loads features (with XHR), parses the features, and adds them to the
 * vector source.
 * @param {string|FeatureUrlFunction} url Feature URL service.
 * @param {import("./format/Feature.js").default} format Feature format.
 * @return {FeatureLoader} The feature loader.
 * @api
 */
export function xhr(url, format) {
  return loadFeaturesXhr(url, format,
    /**
     * @param {Array<import("./Feature.js").default>} features The loaded features.
     * @param {import("./proj/Projection.js").default} dataProjection Data
     * projection.
     * @this {VectorSource|import("./VectorTile.js").default}
     */
    function(features, dataProjection) {
      if (this instanceof VectorSource) {
        this.addFeatures(features);
      }
    }, /* FIXME handle error */ VOID);
}
<|endoftext|>


<commit_before>goog.provide('ol.geom.Geometry');
goog.provide('ol.geom.GeometryLayout');
goog.provide('ol.geom.GeometryType');

goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('ol.Object');
goog.require('ol.extent');
goog.require('ol.proj');
goog.require('ol.proj.Units');

/**
 * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
 * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
 * `'GeometryCollection'`, `'Circle'`.
 * @enum {string}
 * @api stable
 */
ol.geom.GeometryType = {
  POINT: 'Point',
  LINE_STRING: 'LineString',
  LINEAR_RING: 'LinearRing',
  POLYGON: 'Polygon',
  MULTI_POINT: 'MultiPoint',
  MULTI_LINE_STRING: 'MultiLineString',
  MULTI_POLYGON: 'MultiPolygon',
  GEOMETRY_COLLECTION: 'GeometryCollection',
  CIRCLE: 'Circle'
};

/**
 * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
 * or measure ('M') coordinate is available. Supported values are `'XY'`,
 * `'XYZ'`, `'XYM'`, `'XYZM'`.
 * @enum {string}
 * @api stable
 */
ol.geom.GeometryLayout = {
  XY: 'XY',
  XYZ: 'XYZ',
  XYM: 'XYM',
  XYZM: 'XYZM'
};

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Base class for vector geometries.
 *
 * To get notified of changes to the geometry, register a listener for the
 * generic `change` event on your geometry instance.
 *
 * @constructor
 * @extends {ol.Object}
 * @api stable
 */
ol.geom.Geometry = function() {

  goog.base(this);

  /**
   * @private
   * @type {ol.Extent}
   */
  this.extent_ = ol.extent.createEmpty();

  /**
   * @private
   * @type {number}
   */
  this.extentRevision_ = -1;

  /**
   * @protected
   * @type {Object.<string, ol.geom.Geometry>}
   */
  this.simplifiedGeometryCache = {};

  /**
   * @protected
   * @type {number}
   */
  this.simplifiedGeometryMaxMinSquaredTolerance = 0;

  /**
   * @protected
   * @type {number}
   */
  this.simplifiedGeometryRevision = 0;

};
goog.inherits(ol.geom.Geometry, ol.Object);

/**
 * Make a complete copy of the geometry.
 * @function
 * @return {!ol.geom.Geometry} Clone.
 */
ol.geom.Geometry.prototype.clone = goog.abstractMethod;

/**
 * @param {number} x X.
 * @param {number} y Y.
 * @param {ol.Coordinate} closestPoint Closest point.
 * @param {number} minSquaredDistance Minimum squared distance.
 * @return {number} Minimum squared distance.
 */
ol.geom.Geometry.prototype.closestPointXY = goog.abstractMethod;

/**
 * Return the closest point of the geometry to the passed point as
 * {@link ol.Coordinate coordinate}.
 * @param {ol.Coordinate} point Point.
 * @param {ol.Coordinate=} opt_closestPoint Closest point.
 * @return {ol.Coordinate} Closest point.
 * @api stable
 */
ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
  var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
  this.closestPointXY(point[0], point[1], closestPoint, Infinity);
  return closestPoint;
};

/**
 * @param {ol.Coordinate} coordinate Coordinate.
 * @return {boolean} Contains coordinate.
 */
ol.geom.Geometry.prototype.containsCoordinate = function(coordinate) {
  return this.containsXY(coordinate[0], coordinate[1]);
};

/**
 * @param {ol.Extent} extent Extent.
 * @protected
 * @return {ol.Extent} extent Extent.
 */
ol.geom.Geometry.prototype.computeExtent = goog.abstractMethod;

/**
 * @param {number} x X.
 * @param {number} y Y.
 * @return {boolean} Contains (x, y).
 */
ol.geom.Geometry.prototype.containsXY = goog.functions.FALSE;

/**
 * Get the extent of the geometry.
 * @param {ol.Extent=} opt_extent Extent.
 * @return {ol.Extent} extent Extent.
 * @api stable
 */
ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
  if (this.extentRevision_ != this.getRevision()) {
    this.extent_ = this.computeExtent(this.extent_);
    this.extentRevision_ = this.getRevision();
  }
  return ol.extent.returnOrUpdate(this.extent_, opt_extent);
};

/**
 * Rotate the geometry around a given coordinate. This modifies the geometry
 * coordinates in place.
 * @param {number} angle Rotation angle in radians.
 * @param {ol.Coordinate} anchor The rotation center.
 * @api
 */
ol.geom.Geometry.prototype.rotate = goog.abstractMethod;

/**
 * Create a simplified version of this geometry.  For linestrings, this uses
 * the the {@link
 * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
 * Douglas Peucker} algorithm.  For polygons, a quantization-based
 * simplification is used to preserve topology.
 * @function
 * @param {number} tolerance The tolerance distance for simplification.
 * @return {ol.geom.Geometry} A new, simplified version of the original
 *     geometry.
 * @api
 */
ol.geom.Geometry.prototype.simplify = function(tolerance) {
  return this.getSimplifiedGeometry(tolerance * tolerance);
};

/**
 * Create a simplified version of this geometry using the Douglas Peucker
 * algorithm.
 * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
 * @function
 * @param {number} squaredTolerance Squared tolerance.
 * @return {ol.geom.Geometry} Simplified geometry.
 */
ol.geom.Geometry.prototype.getSimplifiedGeometry = goog.abstractMethod;

/**
 * Get the type of this geometry.
 * @function
 * @return {ol.geom.GeometryType} Geometry type.
 */
ol.geom.Geometry.prototype.getType = goog.abstractMethod;

/**
 * Apply a transform function to each coordinate of the geometry.
 * The geometry is modified in place.
 * If you do not want the geometry modified in place, first clone() it and
 * then use this function on the clone.
 * @function
 * @param {ol.TransformFunction} transformFn Transform.
 */
ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;

/**
 * Test if the geometry and the passed extent intersect.
 * @param {ol.Extent} extent Extent.
 * @return {boolean} `true` if the geometry and the extent intersect.
 * @function
 */
ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;

/**
 * Translate the geometry.  This modifies the geometry coordinates in place.  If
 * instead you want a new geometry, first `clone()` this geometry.
 * @param {number} deltaX Delta X.
 * @param {number} deltaY Delta Y.
 * @function
 */
ol.geom.Geometry.prototype.translate = goog.abstractMethod;

/**
 * Transform each coordinate of the geometry from one coordinate reference
 * system to another. The geometry is modified in place.
 * For example, a line will be transformed to a line and a circle to a circle.
 * If you do not want the geometry modified in place, first clone() it and
 * then use this function on the clone.
 *
 * @param {ol.proj.ProjectionLike} source The current projection.  Can be a
 *     string identifier or a {@link ol.proj.Projection} object.
 * @param {ol.proj.ProjectionLike} destination The desired projection.  Can be a
 *     string identifier or a {@link ol.proj.Projection} object.
 * @return {ol.geom.Geometry} This geometry.  Note that original geometry is
 *     modified in place.
 * @api stable
 */
ol.geom.Geometry.prototype.transform = function(source, destination) {
  goog.asserts.assert(
      ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS &&
      ol.proj.get(destination).getUnits() !== ol.proj.Units.TILE_PIXELS,
      'cannot transform geometries with TILE_PIXELS units');
  this.applyTransform(ol.proj.getTransform(source, destination));
  return this;
};
<commit_msg>Add 'function' jsdoc tag to ol.geom.Geometry#rotate<commit_after>goog.provide('ol.geom.Geometry');
goog.provide('ol.geom.GeometryLayout');
goog.provide('ol.geom.GeometryType');

goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('ol.Object');
goog.require('ol.extent');
goog.require('ol.proj');
goog.require('ol.proj.Units');

/**
 * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`,
 * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`,
 * `'GeometryCollection'`, `'Circle'`.
 * @enum {string}
 * @api stable
 */
ol.geom.GeometryType = {
  POINT: 'Point',
  LINE_STRING: 'LineString',
  LINEAR_RING: 'LinearRing',
  POLYGON: 'Polygon',
  MULTI_POINT: 'MultiPoint',
  MULTI_LINE_STRING: 'MultiLineString',
  MULTI_POLYGON: 'MultiPolygon',
  GEOMETRY_COLLECTION: 'GeometryCollection',
  CIRCLE: 'Circle'
};

/**
 * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z')
 * or measure ('M') coordinate is available. Supported values are `'XY'`,
 * `'XYZ'`, `'XYM'`, `'XYZM'`.
 * @enum {string}
 * @api stable
 */
ol.geom.GeometryLayout = {
  XY: 'XY',
  XYZ: 'XYZ',
  XYM: 'XYM',
  XYZM: 'XYZM'
};

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * Base class for vector geometries.
 *
 * To get notified of changes to the geometry, register a listener for the
 * generic `change` event on your geometry instance.
 *
 * @constructor
 * @extends {ol.Object}
 * @api stable
 */
ol.geom.Geometry = function() {

  goog.base(this);

  /**
   * @private
   * @type {ol.Extent}
   */
  this.extent_ = ol.extent.createEmpty();

  /**
   * @private
   * @type {number}
   */
  this.extentRevision_ = -1;

  /**
   * @protected
   * @type {Object.<string, ol.geom.Geometry>}
   */
  this.simplifiedGeometryCache = {};

  /**
   * @protected
   * @type {number}
   */
  this.simplifiedGeometryMaxMinSquaredTolerance = 0;

  /**
   * @protected
   * @type {number}
   */
  this.simplifiedGeometryRevision = 0;

};
goog.inherits(ol.geom.Geometry, ol.Object);

/**
 * Make a complete copy of the geometry.
 * @function
 * @return {!ol.geom.Geometry} Clone.
 */
ol.geom.Geometry.prototype.clone = goog.abstractMethod;

/**
 * @param {number} x X.
 * @param {number} y Y.
 * @param {ol.Coordinate} closestPoint Closest point.
 * @param {number} minSquaredDistance Minimum squared distance.
 * @return {number} Minimum squared distance.
 */
ol.geom.Geometry.prototype.closestPointXY = goog.abstractMethod;

/**
 * Return the closest point of the geometry to the passed point as
 * {@link ol.Coordinate coordinate}.
 * @param {ol.Coordinate} point Point.
 * @param {ol.Coordinate=} opt_closestPoint Closest point.
 * @return {ol.Coordinate} Closest point.
 * @api stable
 */
ol.geom.Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) {
  var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
  this.closestPointXY(point[0], point[1], closestPoint, Infinity);
  return closestPoint;
};

/**
 * @param {ol.Coordinate} coordinate Coordinate.
 * @return {boolean} Contains coordinate.
 */
ol.geom.Geometry.prototype.containsCoordinate = function(coordinate) {
  return this.containsXY(coordinate[0], coordinate[1]);
};

/**
 * @param {ol.Extent} extent Extent.
 * @protected
 * @return {ol.Extent} extent Extent.
 */
ol.geom.Geometry.prototype.computeExtent = goog.abstractMethod;

/**
 * @param {number} x X.
 * @param {number} y Y.
 * @return {boolean} Contains (x, y).
 */
ol.geom.Geometry.prototype.containsXY = goog.functions.FALSE;

/**
 * Get the extent of the geometry.
 * @param {ol.Extent=} opt_extent Extent.
 * @return {ol.Extent} extent Extent.
 * @api stable
 */
ol.geom.Geometry.prototype.getExtent = function(opt_extent) {
  if (this.extentRevision_ != this.getRevision()) {
    this.extent_ = this.computeExtent(this.extent_);
    this.extentRevision_ = this.getRevision();
  }
  return ol.extent.returnOrUpdate(this.extent_, opt_extent);
};

/**
 * Rotate the geometry around a given coordinate. This modifies the geometry
 * coordinates in place.
 * @param {number} angle Rotation angle in radians.
 * @param {ol.Coordinate} anchor The rotation center.
 * @api
 * @function
 */
ol.geom.Geometry.prototype.rotate = goog.abstractMethod;

/**
 * Create a simplified version of this geometry.  For linestrings, this uses
 * the the {@link
 * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
 * Douglas Peucker} algorithm.  For polygons, a quantization-based
 * simplification is used to preserve topology.
 * @function
 * @param {number} tolerance The tolerance distance for simplification.
 * @return {ol.geom.Geometry} A new, simplified version of the original
 *     geometry.
 * @api
 */
ol.geom.Geometry.prototype.simplify = function(tolerance) {
  return this.getSimplifiedGeometry(tolerance * tolerance);
};

/**
 * Create a simplified version of this geometry using the Douglas Peucker
 * algorithm.
 * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
 * @function
 * @param {number} squaredTolerance Squared tolerance.
 * @return {ol.geom.Geometry} Simplified geometry.
 */
ol.geom.Geometry.prototype.getSimplifiedGeometry = goog.abstractMethod;

/**
 * Get the type of this geometry.
 * @function
 * @return {ol.geom.GeometryType} Geometry type.
 */
ol.geom.Geometry.prototype.getType = goog.abstractMethod;

/**
 * Apply a transform function to each coordinate of the geometry.
 * The geometry is modified in place.
 * If you do not want the geometry modified in place, first clone() it and
 * then use this function on the clone.
 * @function
 * @param {ol.TransformFunction} transformFn Transform.
 */
ol.geom.Geometry.prototype.applyTransform = goog.abstractMethod;

/**
 * Test if the geometry and the passed extent intersect.
 * @param {ol.Extent} extent Extent.
 * @return {boolean} `true` if the geometry and the extent intersect.
 * @function
 */
ol.geom.Geometry.prototype.intersectsExtent = goog.abstractMethod;

/**
 * Translate the geometry.  This modifies the geometry coordinates in place.  If
 * instead you want a new geometry, first `clone()` this geometry.
 * @param {number} deltaX Delta X.
 * @param {number} deltaY Delta Y.
 * @function
 */
ol.geom.Geometry.prototype.translate = goog.abstractMethod;

/**
 * Transform each coordinate of the geometry from one coordinate reference
 * system to another. The geometry is modified in place.
 * For example, a line will be transformed to a line and a circle to a circle.
 * If you do not want the geometry modified in place, first clone() it and
 * then use this function on the clone.
 *
 * @param {ol.proj.ProjectionLike} source The current projection.  Can be a
 *     string identifier or a {@link ol.proj.Projection} object.
 * @param {ol.proj.ProjectionLike} destination The desired projection.  Can be a
 *     string identifier or a {@link ol.proj.Projection} object.
 * @return {ol.geom.Geometry} This geometry.  Note that original geometry is
 *     modified in place.
 * @api stable
 */
ol.geom.Geometry.prototype.transform = function(source, destination) {
  goog.asserts.assert(
      ol.proj.get(source).getUnits() !== ol.proj.Units.TILE_PIXELS &&
      ol.proj.get(destination).getUnits() !== ol.proj.Units.TILE_PIXELS,
      'cannot transform geometries with TILE_PIXELS units');
  this.applyTransform(ol.proj.getTransform(source, destination));
  return this;
};
<|endoftext|>