<commit_before>'use strict'
/* eslint-disable no-return-assign */
const qw = require('qw')
const Bluebird = require('bluebird')

let Site

class Fic {
  constructor (fetch) {
    this._id = null
    this.fetch = fetch
    this.title = null
    this.link = null
    this.updateFrom = null
    this.author = null
    this.authorUrl = null
    this.created = null
    this.modified = null
    this.publisher = null
    this.description = null
    this.cover = null
    this.chapterHeadings = null
    this.externals = null
    this.spoilers = null
    this.words = null
    this.tags = []
    this.fics = []
    this.chapters = new ChapterList()
    this.site = null
    this._includeTOC = null
    this._numberTOC = null
    this.fetchMeta = null
    this.scrapeMeta = null
  }

  get id () {
    return this._id || this.link || this.updateFrom
  }
  set id (value) {
    return this._id = value
  }

  get includeTOC () {
    return this._includeTOC === null ? true : this._includeTOC
  }

  set includeTOC (value) {
    this._includeTOC = value
  }

  get numberTOC () {
    return this._numberTOC === null ? true : this._numberTOC
  }

  set numberTOC (value) {
    this._numberTOC = value
  }

  updateWith () {
    return this.updateFrom || this.link
  }

  chapterExists (link) {
    if (link == null) return false
    if (this.chapters.chapterExists(link, this)) return true
    if (this.fics.some(fic => fic.chapterExists(link))) return true
    return false
  }

  normalizeLink (link) {
    try {
      const site = Site.fromUrl(link)
      return site.normalizeLink(link)
    } catch (_) {
      return link
    }
  }

  addChapter (opts) {
    if (this.chapterExists(opts.link) || this.chapterExists(opts.fetchFrom)) return
    if (opts.spoilers === null) opts.spoilers = this.spoilers
    this.chapters.addChapter(opts)
  }

  importFromJSON (raw) {
    const props = qw`id link title author authorUrl created modified
     description tags publisher cover chapterHeadings words updateFrom
     includeTOC numberTOC fetchMeta scrapeMeta`

    for (let prop of props) {
      if (prop in raw) this[prop] = raw[prop]
    }
    this.externals = raw.externals != null ? raw.externals : true
    this.spoilers = raw.spoilers != null ? raw.spoilers : true
    for (let prop of Object.keys(raw)) {
      if (props.indexOf(prop) !== -1) continue
      if (prop !== 'chapters' && prop !== 'fics' && prop !== 'externals' && prop !== 'spoilers') {
        process.emit('warn', `Unknown property when importing fic: "${prop}"`)
      }
    }
    this.chapters.importFromJSON(this, raw)
    if (raw.fics) {
      for (let fic of raw.fics) {
        this.fics.push(SubFic.fromJSON(this, fic))
      }
    }
    try {
      this.site = Site.fromUrl(this.updateWith())
    } catch (ex) {
      process.emit('warn', ex)
    }
    return this
  }

  static fromUrl (fetch, link) {
    const fic = new this(fetch)
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    return fic.site.getFicMetadata(fetch, fic).then(thenMaybeFallback, elseMaybeFallback).thenReturn(fic)
    function elseMaybeFallback (err) {
      if (err && (!err.meta || err.meta.status !== 404)) throw err
      return thenMaybeFallback(err)
    }
    function thenMaybeFallback (err) {
      if (fic.chapters.length === 0 ) {
        fic.scrapeMeta = true
        if (fic.site.canScrape) {
          return fic.site.scrapeFicMetadata(fetch, fic).catch(scrapeErr => Bluebird.reject(err || scrapeErr))
        } else {
          if (!err) {
            err = new Error(`Could not fetch: ${link}`)
            err.code = 404
            err.url = link
          }
          return Bluebird.reject(err)
        }
      } else {
        fic.fetchMeta = true
      }
    }
  }

  static fromUrlAndScrape (fetch, link) {
    const fic = new this(fetch)
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    fic.fetchMeta = true
    fic.scrapeMeta = true
    return fic.site.getFicMetadata(fetch, fic).then(() => {
      if (fic.site.canScrape) {
        return fic.site.scrapeFicMetadata(fetch, fic).thenReturn(fic)
      } else {
        return fic
      }
    })
  }

  static scrapeFromUrl (fetch, link) {
    const fic = new this()
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    fic.scrapeMeta = true
    if (!fic.site.canScrape) {
      const err = new Error(`Site ${fic.site.publisherName || fic.site.publisher} does not support fetching via scraping for ${fic.title} @ ${fic.link}`)
      err.code = 'ENOSCRAPE'
      return Bluebird.reject(err)
    }
    return fic.site.scrapeFicMetadata(fetch, fic).thenReturn(fic)
  }

  static fromJSON (raw) {
    const fic = new this()
    return fic.importFromJSON(raw)
  }

  toJSON () {
    const result = {}
    for (let prop of qw`
         id title link updateFrom author authorUrl created modified publisher cover
         description tags words fics chapters chapterHeadings includeTOC numberTOC fetchMeta scrapeMeta
       `) {
      if (this[prop] != null && (!Array.isArray(this[prop]) || this[prop].length)) result[prop] = this[prop]
    }
    if (!this.externals) result.externals = this.externals
    if (!this.spoilers) result.spoilers = this.spoilers
    return result
  }
}

class SubFic extends Fic {
  constructor (parentFic) {
    super()
    delete this.fics
    this.parent = parentFic
  }
  chapterExists (link) {
    return this.chapters.chapterExists(link, this)
  }
  static fromJSON (parent, raw) {
    const fic = new this(parent)
    fic.importFromJSON(raw)
    return fic
  }
  get author () {
    return this._author || this.parent.author
  }
  set author (value) {
    return this._author = value
  }
  get authorUrl () {
    return this._authorUrl || this.parent.authorUrl
  }
  set authorUrl (value) {
    return this._authorUrl = value
  }
  get publisher () {
    return this._publisher || this.parent.publisher
  }
  set publisher (value) {
    return this._publisher = value
  }
  get link () {
    return this._link || this.chapters[0].link
  }
  set link (value) {
    return this._link = value
  }
  get chapterHeadings () {
    return this._chapterHeadings || this.parent.chapterHeadings
  }
  set chapterHeadings (value) {
    return this._chapterHeadings = value
  }
  get externals () {
    return this._externals || this.parent.externals
  }
  set externals (value) {
    return this._externals = value
  }
  get spoilers () {
    return this._spoilers || this.parent.spoilers
  }
  set spoilers (value) {
    return this._spoilers = value
  }
  get tags () {
    if (!this._tags) return Object.assign([], this.parent.tags)
    return this._tags
  }
  set tags (value) {
    if (value.length === 0) value = null
    return this._tags = value
  }
  toJSON () {
    const result = {}
    for (let prop of qw`
         title _link _author _authorUrl created modified _publisher
         description _tags chapters _chapterHeadings words includeTOC numberTOC
         `) {
      const assignTo = prop[0] === '_' ? prop.slice(1) : prop
      if (this[prop] && (this[prop].length == null || this[prop].length)) result[assignTo] = this[prop]
    }
    return result
  }
}

class ChapterList extends Array {
  chapterExists (link, fic) {
    if (link == null) {
      return
    } else if (fic) {
      const normalizedLink = fic.normalizeLink(link)
      return this.some(chap => fic.normalizeLink(chap.link) === normalizedLink || chap.fetchFrom === normalizedLink)
    } else {
      return this.some(chap => chap.link === link || chap.fetchFrom === link)
    }
  }
  addChapter (opts) {
    if (this.chapterExists(opts.fetchFrom) || this.chapterExists(opts.link)) return
    let name = opts.name
    let ctr = 0
    while (this.some(chap => chap.name === name)) {
      name = opts.name + ' (' + ++ctr + ')'
    }
    if (opts.created && (!this.created || opts.created < this.created)) this.created = opts.created
    this.push(new Chapter(Object.assign({}, opts, {name, order: this.length})))
  }
  importFromJSON (fic, raw) {
    if (raw.fics && !raw.chapters) return
    if (!raw.chapters) {
      const err = new Error('Fic "' + raw.title + '" is missing any chapters.')
      err.code = 'ENOCHAPTERS'
      throw err
    }
    for (let chapter of raw.chapters) {
      if (chapter.spoilers == null) chapter.spoilers = fic.spoilers
      this.push(Chapter.fromJSON(this.length, chapter))
    }
  }
}

class Chapter {
  constructor (opts) {
    this.order = opts.order
    this.name = opts.name
    this.link = opts.link
    this.description = opts.description
    this.fetchFrom = opts.fetchFrom
    this.created = opts.created
    this.modified = opts.modified
    this.author = opts.author
    this.authorUrl = opts.authorUrl
    this.tags = opts.tags
    this.externals = opts.externals != null ? opts.externals : true
    this.spoilers = opts.spoilers != null ? opts.spoilers : true
    this.headings = opts.headings
    this.words = opts.words
  }
  toJSON () {
    return {
      name: this.name,
      description: this.description,
      link: this.link,
      fetchFrom: this.fetchFrom,
      author: this.author,
      authorUrl: this.authorUrl,
      created: this.created === 'Invalid Date' ? null : this.created,
      modified: this.modified === 'Invalid Date' ? null : this.modified,
      tags: this.tags,
      externals: this.externals !== true ? this.externals : null,
      spoilers: this.spoilers !== true ? this.spoilers: null,
      headings: this.headings,
      words: this.words
    }
  }
  static fromJSON (order, opts) {
    return new Chapter(Object.assign({order}, opts))
  }
  fetchWith () {
    return this.fetchFrom || this.link
  }
  getContent (fetch) {
    const site = Site.fromUrl(this.fetchWith())
    return site.getChapter(fetch, this)
  }
  static getContent (fetch, href) {
    return (new this({link: href})).getContent(fetch)
  }
}

module.exports = Fic
module.exports.Chapter = Chapter

// defer 'cause `class` definitions don't hoist
Site = use('site')
<commit_msg>fic: Proxy SubFic.title to default from first chapter name<commit_after>'use strict'
/* eslint-disable no-return-assign */
const qw = require('qw')
const Bluebird = require('bluebird')

let Site

class Fic {
  constructor (fetch) {
    this._id = null
    this.fetch = fetch
    this.title = null
    this.link = null
    this.updateFrom = null
    this.author = null
    this.authorUrl = null
    this.created = null
    this.modified = null
    this.publisher = null
    this.description = null
    this.cover = null
    this.chapterHeadings = null
    this.externals = null
    this.spoilers = null
    this.words = null
    this.tags = []
    this.fics = []
    this.chapters = new ChapterList()
    this.site = null
    this._includeTOC = null
    this._numberTOC = null
    this.fetchMeta = null
    this.scrapeMeta = null
  }

  get id () {
    return this._id || this.link || this.updateFrom
  }
  set id (value) {
    return this._id = value
  }

  get includeTOC () {
    return this._includeTOC === null ? true : this._includeTOC
  }

  set includeTOC (value) {
    this._includeTOC = value
  }

  get numberTOC () {
    return this._numberTOC === null ? true : this._numberTOC
  }

  set numberTOC (value) {
    this._numberTOC = value
  }

  updateWith () {
    return this.updateFrom || this.link
  }

  chapterExists (link) {
    if (link == null) return false
    if (this.chapters.chapterExists(link, this)) return true
    if (this.fics.some(fic => fic.chapterExists(link))) return true
    return false
  }

  normalizeLink (link) {
    try {
      const site = Site.fromUrl(link)
      return site.normalizeLink(link)
    } catch (_) {
      return link
    }
  }

  addChapter (opts) {
    if (this.chapterExists(opts.link) || this.chapterExists(opts.fetchFrom)) return
    if (opts.spoilers === null) opts.spoilers = this.spoilers
    this.chapters.addChapter(opts)
  }

  importFromJSON (raw) {
    const props = qw`id link title author authorUrl created modified
     description tags publisher cover chapterHeadings words updateFrom
     includeTOC numberTOC fetchMeta scrapeMeta`

    for (let prop of props) {
      if (prop in raw) this[prop] = raw[prop]
    }
    this.externals = raw.externals != null ? raw.externals : true
    this.spoilers = raw.spoilers != null ? raw.spoilers : true
    for (let prop of Object.keys(raw)) {
      if (props.indexOf(prop) !== -1) continue
      if (prop !== 'chapters' && prop !== 'fics' && prop !== 'externals' && prop !== 'spoilers') {
        process.emit('warn', `Unknown property when importing fic: "${prop}"`)
      }
    }
    this.chapters.importFromJSON(this, raw)
    if (raw.fics) {
      for (let fic of raw.fics) {
        this.fics.push(SubFic.fromJSON(this, fic))
      }
    }
    try {
      this.site = Site.fromUrl(this.updateWith())
    } catch (ex) {
      process.emit('warn', ex)
    }
    return this
  }

  static fromUrl (fetch, link) {
    const fic = new this(fetch)
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    return fic.site.getFicMetadata(fetch, fic).then(thenMaybeFallback, elseMaybeFallback).thenReturn(fic)
    function elseMaybeFallback (err) {
      if (err && (!err.meta || err.meta.status !== 404)) throw err
      return thenMaybeFallback(err)
    }
    function thenMaybeFallback (err) {
      if (fic.chapters.length === 0 ) {
        fic.scrapeMeta = true
        if (fic.site.canScrape) {
          return fic.site.scrapeFicMetadata(fetch, fic).catch(scrapeErr => Bluebird.reject(err || scrapeErr))
        } else {
          if (!err) {
            err = new Error(`Could not fetch: ${link}`)
            err.code = 404
            err.url = link
          }
          return Bluebird.reject(err)
        }
      } else {
        fic.fetchMeta = true
      }
    }
  }

  static fromUrlAndScrape (fetch, link) {
    const fic = new this(fetch)
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    fic.fetchMeta = true
    fic.scrapeMeta = true
    return fic.site.getFicMetadata(fetch, fic).then(() => {
      if (fic.site.canScrape) {
        return fic.site.scrapeFicMetadata(fetch, fic).thenReturn(fic)
      } else {
        return fic
      }
    })
  }

  static scrapeFromUrl (fetch, link) {
    const fic = new this()
    fic.site = Site.fromUrl(link)
    fic.link = fic.site.link
    fic.scrapeMeta = true
    if (!fic.site.canScrape) {
      const err = new Error(`Site ${fic.site.publisherName || fic.site.publisher} does not support fetching via scraping for ${fic.title} @ ${fic.link}`)
      err.code = 'ENOSCRAPE'
      return Bluebird.reject(err)
    }
    return fic.site.scrapeFicMetadata(fetch, fic).thenReturn(fic)
  }

  static fromJSON (raw) {
    const fic = new this()
    return fic.importFromJSON(raw)
  }

  toJSON () {
    const result = {}
    for (let prop of qw`
         id title link updateFrom author authorUrl created modified publisher cover
         description tags words fics chapters chapterHeadings includeTOC numberTOC fetchMeta scrapeMeta
       `) {
      if (this[prop] != null && (!Array.isArray(this[prop]) || this[prop].length)) result[prop] = this[prop]
    }
    if (!this.externals) result.externals = this.externals
    if (!this.spoilers) result.spoilers = this.spoilers
    return result
  }
}

class SubFic extends Fic {
  constructor (parentFic) {
    super()
    delete this.fics
    this.parent = parentFic
  }
  chapterExists (link) {
    return this.chapters.chapterExists(link, this)
  }
  static fromJSON (parent, raw) {
    const fic = new this(parent)
    fic.importFromJSON(raw)
    return fic
  }
  get author () {
    return this._author || this.parent.author
  }
  set author (value) {
    return this._author = value
  }
  get authorUrl () {
    return this._authorUrl || this.parent.authorUrl
  }
  set authorUrl (value) {
    return this._authorUrl = value
  }
  get publisher () {
    return this._publisher || this.parent.publisher
  }
  set publisher (value) {
    return this._publisher = value
  }
  get title () {
    return this._title || this.chapters[0].name
  }
  set title (value) {
    return this._title = value
  }
  get link () {
    return this._link || this.chapters[0].link
  }
  set link (value) {
    return this._link = value
  }
  get chapterHeadings () {
    return this._chapterHeadings || this.parent.chapterHeadings
  }
  set chapterHeadings (value) {
    return this._chapterHeadings = value
  }
  get externals () {
    return this._externals || this.parent.externals
  }
  set externals (value) {
    return this._externals = value
  }
  get spoilers () {
    return this._spoilers || this.parent.spoilers
  }
  set spoilers (value) {
    return this._spoilers = value
  }
  get tags () {
    if (!this._tags) return Object.assign([], this.parent.tags)
    return this._tags
  }
  set tags (value) {
    if (value.length === 0) value = null
    return this._tags = value
  }
  toJSON () {
    const result = {}
    for (let prop of qw`
         _title _link _author _authorUrl created modified _publisher
         description _tags chapters _chapterHeadings words includeTOC numberTOC
         `) {
      const assignTo = prop[0] === '_' ? prop.slice(1) : prop
      if (this[prop] && (this[prop].length == null || this[prop].length)) result[assignTo] = this[prop]
    }
    return result
  }
}

class ChapterList extends Array {
  chapterExists (link, fic) {
    if (link == null) {
      return
    } else if (fic) {
      const normalizedLink = fic.normalizeLink(link)
      return this.some(chap => fic.normalizeLink(chap.link) === normalizedLink || chap.fetchFrom === normalizedLink)
    } else {
      return this.some(chap => chap.link === link || chap.fetchFrom === link)
    }
  }
  addChapter (opts) {
    if (this.chapterExists(opts.fetchFrom) || this.chapterExists(opts.link)) return
    let name = opts.name
    let ctr = 0
    while (this.some(chap => chap.name === name)) {
      name = opts.name + ' (' + ++ctr + ')'
    }
    if (opts.created && (!this.created || opts.created < this.created)) this.created = opts.created
    this.push(new Chapter(Object.assign({}, opts, {name, order: this.length})))
  }
  importFromJSON (fic, raw) {
    if (raw.fics && !raw.chapters) return
    if (!raw.chapters) {
      const err = new Error('Fic "' + raw.title + '" is missing any chapters.')
      err.code = 'ENOCHAPTERS'
      throw err
    }
    for (let chapter of raw.chapters) {
      if (chapter.spoilers == null) chapter.spoilers = fic.spoilers
      this.push(Chapter.fromJSON(this.length, chapter))
    }
  }
}

class Chapter {
  constructor (opts) {
    this.order = opts.order
    this.name = opts.name
    this.link = opts.link
    this.description = opts.description
    this.fetchFrom = opts.fetchFrom
    this.created = opts.created
    this.modified = opts.modified
    this.author = opts.author
    this.authorUrl = opts.authorUrl
    this.tags = opts.tags
    this.externals = opts.externals != null ? opts.externals : true
    this.spoilers = opts.spoilers != null ? opts.spoilers : true
    this.headings = opts.headings
    this.words = opts.words
  }
  toJSON () {
    return {
      name: this.name,
      description: this.description,
      link: this.link,
      fetchFrom: this.fetchFrom,
      author: this.author,
      authorUrl: this.authorUrl,
      created: this.created === 'Invalid Date' ? null : this.created,
      modified: this.modified === 'Invalid Date' ? null : this.modified,
      tags: this.tags,
      externals: this.externals !== true ? this.externals : null,
      spoilers: this.spoilers !== true ? this.spoilers: null,
      headings: this.headings,
      words: this.words
    }
  }
  static fromJSON (order, opts) {
    return new Chapter(Object.assign({order}, opts))
  }
  fetchWith () {
    return this.fetchFrom || this.link
  }
  getContent (fetch) {
    const site = Site.fromUrl(this.fetchWith())
    return site.getChapter(fetch, this)
  }
  static getContent (fetch, href) {
    return (new this({link: href})).getContent(fetch)
  }
}

module.exports = Fic
module.exports.Chapter = Chapter

// defer 'cause `class` definitions don't hoist
Site = use('site')
<|endoftext|>


<commit_before>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var radiusParticle = canvas.height/50;
var numParticles = 100;
var Dt = 1;
var minD = 2*radiusParticle;

var gas = new Gas(numParticles, canvas.width - minD, canvas.height - minD);
// drawParticles(gas, ctx, radiusParticle);
setInterval(function () { gas.move(); }, 10);

function drawParticles(gas, ctx, rad) {
    for (var i = 0; i < gas.numParticles; i++) {
        part = gas.particles[i];
        // ctx.translate(part.pos.x, part.pos.y);
        ctx.beginPath();
        ctx.arc(part.pos.x, part.pos.y, rad, 0, 2*Math.PI);
        ctx.stroke();
        // ctx.translate(-part.pos.x, -part.pos.y);
    }
}

function Particle(posx, posy, velx, vely) {
    this.pos = {x: posx, y: posy};
    this.vel = {vx: velx, vy: vely};
    this.move = moveParticle;
}

function moveParticle() {
    var posx = this.pos.x;
    var posy = this.pos.y;
    if (posx + radiusParticle > canvas.width || posx - radiusParticle < 0) {
        this.vel.vx *= -1;
    }
    if (posy + radiusParticle > canvas.height || posy - radiusParticle < 0) {
        this.vel.vy *= -1;
    }
    this.pos = {
        x: posx + this.vel.vx*Dt,
        y: posy + this.vel.vy*Dt
    };
}

function Gas(numParticles, lx, ly) {
    this.numParticles = numParticles;
    this.particles = [];
    this.size = {lx: lx, ly: ly};
    this.move = moveGas;

    for (var i = 0; i < numParticles; i++) {
        var pos = newPos(lx, ly);
        var part = new Particle(pos.x, pos.y, Math.random()*2-1, Math.random()*2-1);

        this.particles.push(part);
    }
}

function newPos(lx, ly) {
    return {
        x: lx * Math.random() + radiusParticle,
        y: ly * Math.random() + radiusParticle
    };
}

function distParticles(a, b) {
    dx = b.pos.x - a.pos.x;
    dy = b.pos.y - a.pos.y;
    return {
        norm: Math.sqrt(dx*dx + dy*dy),
        dx: dx,
        dy: dy
    }
}

function checkColision(gas) {
    for (var i = 0; i < gas.numParticles; i++) {
        a = gas.particles[i];

        for (var j = i+1; j < this.numParticles; j++) {
            b = gas.particles[j];
            var dist = distParticles(a, b);
            if (dist.norm > 2 && dist.norm < minD) {
            // if (dist.norm < minD) {
                // Si hay colisión:
                rx = dist.dx / dist.norm;
                ry = dist.dy / dist.norm;

                dvx = b.vel.vx - a.vel.vx;
                dvy = b.vel.vy - a.vel.vy;

                //(vb - va)·r
                var projection = rx * dvx + ry * dvy;
                a.vel.vx += projection * rx;
                a.vel.vy += projection * ry;

                b.vel.vx -= projection * rx;
                b.vel.vy -= projection * ry;
            }
        }
    }
}

function moveGas() {
    checkColision(this);
    for (var i = 0; i < this.numParticles; i++){
        this.particles[i].move();
    }
    ctx.clearRect(0,0,canvas.width,canvas.height)
    drawParticles(gas, ctx, radiusParticle);
}
<commit_msg>reescalé problema adimensionalmente<commit_after>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var numParticles = 100;
var radiusParticle = 1/50;
var Dt = 1/200;
var minD = 2*radiusParticle;
var lx = 1;
var ly = 1;

var gas = new Gas(numParticles, lx - minD, ly - minD);
setInterval(function () { gas.move(); }, 33);

function Gas(numParticles, lx, ly) {
    this.numParticles = numParticles;
    this.particles = [];
    this.size = {lx: lx, ly: ly};
    this.move = moveGas;

    for (var i = 0; i < numParticles; i++) {
        var pos = newPos(lx, ly);
        var part = new Particle(pos.x, pos.y, Math.random()*2-1, Math.random()*2-1);

        this.particles.push(part);
    }
}

function moveGas() {
    checkColision(this);
    for (var i = 0; i < this.numParticles; i++){
        this.particles[i].move();
    }
    ctx.clearRect(0,0,canvas.width,canvas.height)
    drawParticles(gas);
}

function drawParticles(gas) {
    for (var i = 0; i < gas.numParticles; i++) {
        part = gas.particles[i];

        ctx.beginPath();
        ctx.arc(canvas.width * part.pos.x, canvas.height * part.pos.y,
            Math.min(canvas.width, canvas.height)*radiusParticle, 0, 2*Math.PI);
        ctx.stroke();
    }
}

function newPos(lx, ly) {
    return {
        x: lx * Math.random() + radiusParticle,
        y: ly * Math.random() + radiusParticle
    };
}

function checkColision(gas) {
    for (var i = 0; i < gas.numParticles; i++) {
        a = gas.particles[i];

        for (var j = i+1; j < this.numParticles; j++) {
            b = gas.particles[j];
            var dist = distParticles(a, b);
            if (dist.norm < minD) {
                // Si hay colisión:
                // if (a.counterParticles == 0) {
                    rx = dist.dx / dist.norm;
                    ry = dist.dy / dist.norm;

                    dvx = b.vel.vx - a.vel.vx;
                    dvy = b.vel.vy - a.vel.vy;

                    //(vb - va)·r
                    var projection = rx * dvx + ry * dvy;
                    a.vel.vx += projection * rx;
                    a.vel.vy += projection * ry;

                    b.vel.vx -= projection * rx;
                    b.vel.vy -= projection * ry;
                // }
                // a.counterParticles++; b.counterParticles++;
            }
            // else { a.counterParticles = 0; }
        }
    }
}

function distParticles(a, b) {
    dx = b.pos.x - a.pos.x;
    dy = b.pos.y - a.pos.y;
    return {
        norm: Math.sqrt(dx*dx + dy*dy),
        dx: dx,
        dy: dy
    }
}

function Particle(posx, posy, velx, vely) {
    this.pos = {x: posx, y: posy};
    this.vel = {vx: velx, vy: vely};
    this.move = moveParticle;
    // this.counterWalls = 0;
    // this.counterParticles = 0;
}

function moveParticle() {
    var posx = this.pos.x;
    var posy = this.pos.y;
    if (posx + radiusParticle > lx || posx - radiusParticle < 0) {
        this.vel.vx *= -1;
        // if (this.counterWalls == 0) { this.vel.vx *= -1; }
        // this.counterWalls++
    }
    // else
    if (posy + radiusParticle > ly || posy - radiusParticle < 0) {
        this.vel.vy *= -1;
        // if (this.counterWalls == 0) { this.vel.vy *= -1; }
        // this.counterWalls++;
    }
    // else {
    //     this.counterWalls = 0
    // }
    this.pos = {
        x: posx + this.vel.vx*Dt,
        y: posy + this.vel.vy*Dt
    };

}
<|endoftext|>


<commit_before>/**
 * @class  	Geo
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 * Provide useful method for geolocation events
 *
 */

/**
 * * **accuracy**: Accuracy of Geo. Must be one of `"ACCURACY_HIGH"`, `"ACCURACY_LOW"`
 * * **useGoogleForGeocode**: Tell to use Google Services instead of Titanium geocoding services.
 * @type {Object}
 */
var config = _.extend({
	accuracy: "ACCURACY_HIGH",
	useGoogleForGeocode: true,
}, Alloy.CFG.geo);
exports.config = config;

function checkForServices() {
	return !!Ti.Geolocation.locationServicesEnabled;
}

/**
 * Alert the user that Location is off
 */
function enableServicesAlert(){
	if (OS_IOS) {
		require('T/util').alert(L('geo_error_title'), L('geo_error_msg'));
	} else {
		require('T/util').simpleAlert(L('geo_error_title'));
	}
}
exports.enableServicesAlert = enableServicesAlert;

/**
 * @deprecated: Use `@getPosition` instead.
 * @param {Function} callback
 */
function localize(callback) {
	Ti.API.warn("[DEPRECATED] The use of 'Geo.localize' is deprecated, use 'Geo.getPosition' instead!");
	getCurrentPosition({
		success: function(e){
			callback({ coords: e });
		},
		error: callback
	});
}
exports.localize = localize;

function decorateRequest(request) {
	if (request.decorated) return request;

	if (request.error===undefined) {
		request.error = function(e) {
			if (e.servicesDisabled) {
				enableServicesAlert();
			} else {
				require('T/util').simpleAlert(L('geo_error_title'));
			}
		};
	}

	request.decorated = true;
	return request;
}

/**
 * Get the current GPS coordinates of user using `Ti.Geolocation.getCurrentPosition`
 *
 * A `geo.start` event is fired at start, and a `geo.end` event is fired on end
 *
 * @param {Object} opt Dictionary for this request
 */
function getCurrentPosition(request) {
	request = decorateRequest(request);

	if (false===checkForServices()) {
		if (_.isFunction(request.error)) request.error({ servicesDisabled: true });
		return;
	}

	if (!request.silent) Ti.App.fireEvent('geo.start');

	Ti.Geolocation.getCurrentPosition(function(e){
		if (!request.silent) Ti.App.fireEvent('geo.end');

		if (e.error) {
			if (_.isFunction(request.error)) request.error({});
			return;
		}

		if (!_.isObject(e.coords)) {
			if (_.isFunction(request.error)) request.error({});
			return;
		}

		if (_.isFunction(request.success)) request.success(e.coords);
	});
}
exports.getCurrentPosition = getCurrentPosition;

/**
 * Open Apple Maps on iOS, Google Maps on Android and route from user location to defined location
 *
 * @param  {Number} lat  	Desination latitude
 * @param  {Number} lng  	Destination longitude
 * @param  {String} [mode] GPS mode used (walking,driving)
 */
function startNavigator(lat, lng, mode) {
	getCurrentPosition({
		success: function(g) {
			var D = OS_IOS ? "http://maps.apple.com/" : "https://maps.google.com/maps/";
			Ti.Platform.openURL(D + require('T/util').buildQuery({
				directionsmode: mode || 'walking',
				saddr: g.latitude + "," + g.longitude,
				daddr: lat + "," + lng
			}));
		}
	});
}
exports.startNavigator = startNavigator;

/**
 * Return the coordinates of an address
 *
 * If some errors occurs, the callback in invoked
 * anyway with `{ error: true, success: false }`
 *
 * @param  {String}   address 	The address to geocode
 * @param  {Function} cb      	The callback
 */
function geocode(address, cb) {
	if (config.useGoogleForGeocode) {

		require('T/net').send({
			url: 'http://maps.googleapis.com/maps/api/geocode/json',
			cache: false,
			data: {
				address: address,
				sensor: 'false'
			},
			mime: 'json',
			success: function(res){

				if (res.status!='OK' || !res.results.length) {
					cb({ error: true });
				} else {
					cb({
						success: true,
						latitude: res.results[0].geometry.location.lat,
						longitude: res.results[0].geometry.location.lng
					});
				}

			},
			error: function(err){
				Ti.API.error("Geo: "+err);
				cb({ error: true });
			}
		});

	} else {

		Ti.Geolocation.forwardGeocoder(address, function(res){

			if (!res.success) {
				cb({ error: true });
			} else {
				cb({
					success: true,
					latitude: res.latitude,
					longitude: res.longitude
				});
			}

		});
	}
}
exports.geocode = geocode;

/**
 * Return the address with the specified coordinates
 *
 * If some errors occurs, the callback in invoked
 * anyway with `{ error: true, success: false }`
 *
 * @param  {Number}   lat 	The latitude of the address
 * @param  {Number}   lng 	The longitude of the address
 * @param  {Function} cb  The callback
 */
function reverseGeocode(lat, lng, cb) {
	if (!lat || !lng) {
		return cb({ error: true });
	}

	if (config.useGoogleForGeocode) {

		require('T/net').send({
			url: 'http://maps.googleapis.com/maps/api/geocode/json',
			noCache: true,
			data: {
				latlng: lat+','+lng,
				sensor: 'false'
			},
			mime: 'json',
			success: function(res){

				if (res.status!='OK' || !res.results.length) {
					cb({ error: true });
				} else {
					cb({
						success: true,
						address: res.results[0].formatted_address,
						results: res.results
					});
				}

			},
			error: function(err){
				Ti.API.error("Geo: "+err);
				cb({ error: true });
			}
		});

	} else {

		Ti.Geolocation.reverseGeocoder(lat, lng, function(res){

			if (!res.success || !res.places || !res.places.length) {
				cb({ error: true });
			} else {
				cb({
					success: true,
					address: res.places[0].address,
					results: res.places
				});
			}

		});
	}
}
exports.reverseGeocode = reverseGeocode;

(function init(){

	Ti.Geolocation.purpose = L('geo_purpose');
	Ti.Geolocation.accuracy = Ti.Geolocation[config.accuracy];

})();
<commit_msg>error handler in geo<commit_after>/**
 * @class  	Geo
 * @author  Flavio De Stefano <flavio.destefano@caffeinalab.com>
 * Provide useful method for geolocation events
 *
 */

/**
 * * **accuracy**: Accuracy of Geo. Must be one of `"ACCURACY_HIGH"`, `"ACCURACY_LOW"`
 * * **useGoogleForGeocode**: Tell to use Google Services instead of Titanium geocoding services.
 * @type {Object}
 */
var config = _.extend({
	accuracy: "ACCURACY_HIGH",
	useGoogleForGeocode: true,
}, Alloy.CFG.geo);
exports.config = config;

function decorateRequest(request) {
	if (request.decorated) return request;

	if (request.error===undefined) request.error = originalErrorHandler;

	request.decorated = true;
	return request;
}

/**
 * Alert the user that Location is off
 */
function enableServicesAlert(){
	if (OS_IOS) {
		require('T/util').alert(L('geo_error_title'), L('geo_error_msg'));
	} else {
		require('T/util').simpleAlert(L('geo_error_title'));
	}
}
exports.enableServicesAlert = enableServicesAlert;

/**
 * The original error handler
 * @param  {Object} e
 */
function originalErrorHandler(e) {
	if (e.servicesDisabled) {
		enableServicesAlert();
	} else {
		require('T/util').simpleAlert(L('geo_error_title'));
	}
}
exports.originalErrorHandler = errorHandler;

function checkForServices() {
	return !!Ti.Geolocation.locationServicesEnabled;
}

/**
 * @deprecated: Use `@getPosition` instead.
 * @param {Function} callback
 */
function localize(callback) {
	Ti.API.warn("[DEPRECATED] The use of 'Geo.localize' is deprecated, use 'Geo.getPosition' instead!");
	getCurrentPosition({
		success: function(e){
			callback({ coords: e });
		},
		error: callback
	});
}
exports.localize = localize;

/**
 * Get the current GPS coordinates of user using `Ti.Geolocation.getCurrentPosition`
 *
 * A `geo.start` event is fired at start, and a `geo.end` event is fired on end
 *
 * @param {Object} opt Dictionary for this request
 */
function getCurrentPosition(request) {
	request = decorateRequest(request);

	if (false===checkForServices()) {
		if (_.isFunction(request.complete)) request.complete();

		if (_.isFunction(request.error)) request.error({ servicesDisabled: true });
		return;
	}

	if (!request.silent) Ti.App.fireEvent('geo.start');

	Ti.Geolocation.getCurrentPosition(function(e){
		if (!request.silent) Ti.App.fireEvent('geo.end');
		if (_.isFunction(request.complete)) request.complete();

		if (e.error) {
			if (_.isFunction(request.error)) request.error({});
			return;
		}

		if (!_.isObject(e.coords)) {
			if (_.isFunction(request.error)) request.error({});
			return;
		}

		if (_.isFunction(request.success)) request.success(e.coords);
	});
}
exports.getCurrentPosition = getCurrentPosition;

/**
 * Open Apple Maps on iOS, Google Maps on Android and route from user location to defined location
 *
 * @param  {Number} lat  	Desination latitude
 * @param  {Number} lng  	Destination longitude
 * @param  {String} [mode] GPS mode used (walking,driving)
 */
function startNavigator(lat, lng, mode) {
	getCurrentPosition({
		success: function(g) {
			var D = OS_IOS ? "http://maps.apple.com/" : "https://maps.google.com/maps/";
			Ti.Platform.openURL(D + require('T/util').buildQuery({
				directionsmode: mode || 'walking',
				saddr: g.latitude + "," + g.longitude,
				daddr: lat + "," + lng
			}));
		}
	});
}
exports.startNavigator = startNavigator;

/**
 * Return the coordinates of an address
 *
 * If some errors occurs, the callback in invoked
 * anyway with `{ error: true, success: false }`
 *
 * @param  {String}   address 	The address to geocode
 * @param  {Function} cb      	The callback
 */
function geocode(address, cb) {
	if (config.useGoogleForGeocode) {

		require('T/net').send({
			url: 'http://maps.googleapis.com/maps/api/geocode/json',
			cache: false,
			data: {
				address: address,
				sensor: 'false'
			},
			mime: 'json',
			success: function(res){

				if (res.status!='OK' || !res.results.length) {
					cb({ error: true });
				} else {
					cb({
						success: true,
						latitude: res.results[0].geometry.location.lat,
						longitude: res.results[0].geometry.location.lng
					});
				}

			},
			error: function(err){
				Ti.API.error("Geo: "+err);
				cb({ error: true });
			}
		});

	} else {

		Ti.Geolocation.forwardGeocoder(address, function(res){

			if (!res.success) {
				cb({ error: true });
			} else {
				cb({
					success: true,
					latitude: res.latitude,
					longitude: res.longitude
				});
			}

		});
	}
}
exports.geocode = geocode;

/**
 * Return the address with the specified coordinates
 *
 * If some errors occurs, the callback in invoked
 * anyway with `{ error: true, success: false }`
 *
 * @param  {Number}   lat 	The latitude of the address
 * @param  {Number}   lng 	The longitude of the address
 * @param  {Function} cb  The callback
 */
function reverseGeocode(lat, lng, cb) {
	if (!lat || !lng) {
		return cb({ error: true });
	}

	if (config.useGoogleForGeocode) {

		require('T/net').send({
			url: 'http://maps.googleapis.com/maps/api/geocode/json',
			noCache: true,
			data: {
				latlng: lat+','+lng,
				sensor: 'false'
			},
			mime: 'json',
			success: function(res){

				if (res.status!='OK' || !res.results.length) {
					cb({ error: true });
				} else {
					cb({
						success: true,
						address: res.results[0].formatted_address,
						results: res.results
					});
				}

			},
			error: function(err){
				Ti.API.error("Geo: "+err);
				cb({ error: true });
			}
		});

	} else {

		Ti.Geolocation.reverseGeocoder(lat, lng, function(res){

			if (!res.success || !res.places || !res.places.length) {
				cb({ error: true });
			} else {
				cb({
					success: true,
					address: res.places[0].address,
					results: res.places
				});
			}

		});
	}
}
exports.reverseGeocode = reverseGeocode;

(function init(){

	Ti.Geolocation.purpose = L('geo_purpose');
	Ti.Geolocation.accuracy = Ti.Geolocation[config.accuracy];

})();
<|endoftext|>


<commit_before>define(function(require, module, exports) {
    main.consumes = [
        "Plugin", "build", "settings", "commands", "fs", "save",
        "menus", "tabManager", "ui", "dialog.error"
    ];
    main.provides = ["build.gui"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var settings    = imports.settings;
        var commands    = imports.commands;
        var menus       = imports.menus;
        var save        = imports.save;
        var build       = imports.build;
        var fs          = imports.fs;
        var ui          = imports.ui;
        var tabs        = imports.tabManager;
        var showError   = imports["dialog.error"].show;
        var uCaseFirst  = require("c9/string").uCaseFirst;

        /***** Initialization *****/

        var plugin  = new Plugin("Ajax.org", main.consumes);
        // var emit    = plugin.getEmitter();

        var process, currentBuilder;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Commands
            commands.addCommand({
                name    : "build",
                group   : "Run & Debug",
                hint    : "builds the current file (focussed document)",
                bindKey : { mac: "Command-B", win: "Ctrl-B" },
                isAvailable : function(){
                    return getFocusTab() ? true : false;
                },
                exec : function(){
                    buildFocusTab();
                }
            }, plugin);

            commands.addCommand({
                name    : "stopbuild",
                group   : "Run & Debug",
                hint    : "stop a running build",
                bindKey : { mac: "Ctrl-Shift-C", win: "Ctrl-Shift-C" },
                isAvailable : function(){
                    return process && process.running;
                },
                exec    : function(){
                    process && process.stop();
                }
            }, plugin);

            // Settings
            settings.on("read", function(){
                settings.setDefaults("project/build", [
                    ["saveall", "true"],
                    ["builder", "auto"]
                ]);
                settings.setDefaults("user/build", [
                    ["autobuild", "true"]
                ]);

                var name = settings.get("project/build/@builder");
                setCurrentBuilder(name, function(){});
            });

            // Menus
            var c = 10000;
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            var mnuBuildSystem = new ui.menu({
                "onprop.visible": function(e){
                    if (e.value) {
                        build.listBuilders(function(err, names){
                            var nodes = mnuBuildSystem.childNodes;
                            for (var i = nodes.length - 3; i >= 2; i--) {
                                mnuBuildSystem.removeChild(nodes[i]);
                            }

                            var builder = settings.get("project/build/@builder");
                            if (builder == "auto")
                                nodes[0].select();

                            var c = 300;
                            names.forEach(function(name){
                                menus.addItemToMenu(mnuBuildSystem, new ui.item({
                                    type     : "radio",
                                    caption  : uCaseFirst(name),
                                    value    : name,
                                    selected : builder == name
                                }), c++, plugin);
                            });
                        });
                    }
                },
                "onitemclick": function(e){
                    if (e.value == "new-build-system") {
                        tabs.open({
                            path   : settings.get("project/build/@path")
                              + "/New Build System",
                            active : true,
                            value  : '// Create a custom Cloud9 build system - similar to the Sublime build system\n'
                              + '// For more information see http://docs.c9.io:8080/#!/api/run-method-run\n'
                              + '{\n'
                              + '    "caption" : "",\n'
                              + '    "cmd" : ["ls"],\n'
                              + '    "selector": "source.ext"\n'
                              + '}',
                            document : {
                                meta : {
                                    newfile: true
                                },
                                ace : {
                                    customSyntax : "javascript"
                                }
                            }
                        }, function(){});
                        return;
                    }

                    setCurrentBuilder(e.value, function(){});
                    settings.set("project/build/@builder", e.value);
                }
            });

            menus.addItemByPath("Run/Build System/", mnuBuildSystem,
                c += 100, plugin);
            menus.addItemByPath("Run/Build", new ui.item({
                command : "build"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Cancel Build", new ui.item({
                command : "stopbuild"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Build Result", new ui.item({
                onclick: function(){
                    commands.exec("showoutput", null, { id: "build" });
                }
            }), c += 100, plugin);
            menus.addItemByPath("Run/Automatically Build Supported Files", new ui.item({
                type  : "check",
                value : "[{settings.model}::user/build/@autobuild]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Save All on Build", new ui.item({
                type  : "check",
                value : "[{settings.model}::project/build/@saveall]"
            }), c += 100, plugin);

            c = 0;
            menus.addItemByPath("Run/Build System/Automatic", new ui.item({
                type  : "radio",
                value : "auto"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Build System/~", new ui.divider(), c += 100, plugin);
            menus.addItemByPath("Run/Build System/~", new ui.divider(), c += 1000, plugin);
            menus.addItemByPath("Run/Build System/New Build System", new ui.item({
                value : "new-build-system"
            }), c += 100, plugin);

            // Hook into FS and build file when writeFile is triggered
            save.on("afterSave", function(e){
                if (!settings.getBool("user/build/@autobuild"))
                    return;

                var ext = fs.getExtension(e.path);
                if (!ext)
                    return;

                // @todo consider making this a hash map
                if (currentBuilder == "auto") {
                    if (Object.keys(build.builders).every(function(name){
                        return build.builders[name].selector != "source." + ext;
                    })) return;
                }
                else if (currentBuilder.selector != "source." + ext)
                    return;

                buildFocusTab(true, e.path);
            });
        };

        /***** Methods *****/

        function setCurrentBuilder(name, callback){
            currentBuilder = name;
            if (currentBuilder != "auto") {
                build.getBuilder(currentBuilder, true, function(err, builder){
                    if (err)
                        currentBuilder = "auto";
                    else
                        currentBuilder = builder;
                    callback(err, builder);
                });
            }
        }

        function getFocusTab(){
            var tab = tabs.focussedTab;
            if (!tab) return false;
            if (tab.path) return tab;
            if (tab.editor.type != "output") return false;

            var splits = tab.pane.aml
                .parentNode.parentNode.getElementsByTagName("tab");
            if (splits.length > 1) {
                var idx = splits[0].cloud9pane == tab.pane ? 1 : 0;
                tab = splits[idx].cloud9pane.getTab();
                return tab;
            }
            return false;
        }

        function buildFocusTab(onlyBuild, path){
            if (!path) {
                var tab = getFocusTab();
                if (!tab) return;
                path = tab.path;
            }

            if (!onlyBuild)
                commands.exec("showoutput", null, { id: "build" });

            if (settings.get("project/build/@saveall"))
                save.saveAll(done);
            else
                done();

            function done(){
                process = build.build(currentBuilder,
                    { path: path }, "build", function(err, pid){
                        if (err && err.code != "EBUILDERNOTFOUND")
                            return showError(err);
                    });
            }
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            loaded = false;
        });

        /***** Register and define API *****/

        /**
         * UI for the {@link build} plugin. This plugin is responsible for the Run
         * menu in the main menu bar, as well as the settings and the
         * preferences UI for the run plugin.
         * @singleton
         */
        /**
         * @command build Builds the currently focussed tab.
         */
        /**
         * @command stopbuild Stops the running build.
         */
        plugin.freezePublicAPI({

        });

        register(null, {
            "build.gui": plugin
        });
    }
});
<commit_msg>Show $args in default templates<commit_after>define(function(require, module, exports) {
    main.consumes = [
        "Plugin", "build", "settings", "commands", "fs", "save",
        "menus", "tabManager", "ui", "dialog.error"
    ];
    main.provides = ["build.gui"];
    return main;

    function main(options, imports, register) {
        var Plugin      = imports.Plugin;
        var settings    = imports.settings;
        var commands    = imports.commands;
        var menus       = imports.menus;
        var save        = imports.save;
        var build       = imports.build;
        var fs          = imports.fs;
        var ui          = imports.ui;
        var tabs        = imports.tabManager;
        var showError   = imports["dialog.error"].show;
        var uCaseFirst  = require("c9/string").uCaseFirst;

        /***** Initialization *****/

        var plugin  = new Plugin("Ajax.org", main.consumes);
        // var emit    = plugin.getEmitter();

        var process, currentBuilder;

        var loaded = false;
        function load(){
            if (loaded) return false;
            loaded = true;

            // Commands
            commands.addCommand({
                name    : "build",
                group   : "Run & Debug",
                hint    : "builds the current file (focussed document)",
                bindKey : { mac: "Command-B", win: "Ctrl-B" },
                isAvailable : function(){
                    return getFocusTab() ? true : false;
                },
                exec : function(){
                    buildFocusTab();
                }
            }, plugin);

            commands.addCommand({
                name    : "stopbuild",
                group   : "Run & Debug",
                hint    : "stop a running build",
                bindKey : { mac: "Ctrl-Shift-C", win: "Ctrl-Shift-C" },
                isAvailable : function(){
                    return process && process.running;
                },
                exec    : function(){
                    process && process.stop();
                }
            }, plugin);

            // Settings
            settings.on("read", function(){
                settings.setDefaults("project/build", [
                    ["saveall", "true"],
                    ["builder", "auto"]
                ]);
                settings.setDefaults("user/build", [
                    ["autobuild", "true"]
                ]);

                var name = settings.get("project/build/@builder");
                setCurrentBuilder(name, function(){});
            });

            // Menus
            var c = 10000;
            menus.addItemByPath("Run/~", new ui.divider(), c += 100, plugin);

            var mnuBuildSystem = new ui.menu({
                "onprop.visible": function(e){
                    if (e.value) {
                        build.listBuilders(function(err, names){
                            var nodes = mnuBuildSystem.childNodes;
                            for (var i = nodes.length - 3; i >= 2; i--) {
                                mnuBuildSystem.removeChild(nodes[i]);
                            }

                            var builder = settings.get("project/build/@builder");
                            if (builder == "auto")
                                nodes[0].select();

                            var c = 300;
                            names.forEach(function(name){
                                menus.addItemToMenu(mnuBuildSystem, new ui.item({
                                    type     : "radio",
                                    caption  : uCaseFirst(name),
                                    value    : name,
                                    selected : builder == name
                                }), c++, plugin);
                            });
                        });
                    }
                },
                "onitemclick": function(e){
                    if (e.value == "new-build-system") {
                        tabs.open({
                            path   : settings.get("project/build/@path")
                              + "/New Build System",
                            active : true,
                            value  : '// Create a custom Cloud9 build system - similar to the Sublime build system\n'
                              + '// For more information see http://docs.c9.io:8080/#!/api/run-method-run\n'
                              + '{\n'
                              + '    "caption" : "",\n'
                              + '    "cmd" : ["ls", "$file", "$args"],\n'
                              + '    "info" : "Building $project_path/$file",\n'
                              + '    "selector": "source.ext"\n'
                              + '}',
                            document : {
                                meta : {
                                    newfile: true
                                },
                                ace : {
                                    customSyntax : "javascript"
                                }
                            }
                        }, function(){});
                        return;
                    }

                    setCurrentBuilder(e.value, function(){});
                    settings.set("project/build/@builder", e.value);
                }
            });

            menus.addItemByPath("Run/Build System/", mnuBuildSystem,
                c += 100, plugin);
            menus.addItemByPath("Run/Build", new ui.item({
                command : "build"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Cancel Build", new ui.item({
                command : "stopbuild"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Show Build Result", new ui.item({
                onclick: function(){
                    commands.exec("showoutput", null, { id: "build" });
                }
            }), c += 100, plugin);
            menus.addItemByPath("Run/Automatically Build Supported Files", new ui.item({
                type  : "check",
                value : "[{settings.model}::user/build/@autobuild]"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Save All on Build", new ui.item({
                type  : "check",
                value : "[{settings.model}::project/build/@saveall]"
            }), c += 100, plugin);

            c = 0;
            menus.addItemByPath("Run/Build System/Automatic", new ui.item({
                type  : "radio",
                value : "auto"
            }), c += 100, plugin);
            menus.addItemByPath("Run/Build System/~", new ui.divider(), c += 100, plugin);
            menus.addItemByPath("Run/Build System/~", new ui.divider(), c += 1000, plugin);
            menus.addItemByPath("Run/Build System/New Build System", new ui.item({
                value : "new-build-system"
            }), c += 100, plugin);

            // Hook into FS and build file when writeFile is triggered
            save.on("afterSave", function(e){
                if (!settings.getBool("user/build/@autobuild"))
                    return;

                var ext = fs.getExtension(e.path);
                if (!ext)
                    return;

                // @todo consider making this a hash map
                if (currentBuilder == "auto") {
                    if (Object.keys(build.builders).every(function(name){
                        return build.builders[name].selector != "source." + ext;
                    })) return;
                }
                else if (currentBuilder.selector != "source." + ext)
                    return;

                buildFocusTab(true, e.path);
            });
        };

        /***** Methods *****/

        function setCurrentBuilder(name, callback){
            currentBuilder = name;
            if (currentBuilder != "auto") {
                build.getBuilder(currentBuilder, true, function(err, builder){
                    if (err)
                        currentBuilder = "auto";
                    else
                        currentBuilder = builder;
                    callback(err, builder);
                });
            }
        }

        function getFocusTab(){
            var tab = tabs.focussedTab;
            if (!tab) return false;
            if (tab.path) return tab;
            if (tab.editor.type != "output") return false;

            var splits = tab.pane.aml
                .parentNode.parentNode.getElementsByTagName("tab");
            if (splits.length > 1) {
                var idx = splits[0].cloud9pane == tab.pane ? 1 : 0;
                tab = splits[idx].cloud9pane.getTab();
                return tab;
            }
            return false;
        }

        function buildFocusTab(onlyBuild, path){
            if (!path) {
                var tab = getFocusTab();
                if (!tab) return;
                path = tab.path;
            }

            if (!onlyBuild)
                commands.exec("showoutput", null, { id: "build" });

            if (settings.get("project/build/@saveall"))
                save.saveAll(done);
            else
                done();

            function done(){
                process = build.build(currentBuilder,
                    { path: path }, "build", function(err, pid){
                        if (err && err.code != "EBUILDERNOTFOUND")
                            return showError(err);
                    });
            }
        }

        /***** Lifecycle *****/

        plugin.on("load", function(){
            load();
        });
        plugin.on("enable", function(){

        });
        plugin.on("disable", function(){

        });
        plugin.on("unload", function(){
            loaded = false;
        });

        /***** Register and define API *****/

        /**
         * UI for the {@link build} plugin. This plugin is responsible for the Run
         * menu in the main menu bar, as well as the settings and the
         * preferences UI for the run plugin.
         * @singleton
         */
        /**
         * @command build Builds the currently focussed tab.
         */
        /**
         * @command stopbuild Stops the running build.
         */
        plugin.freezePublicAPI({

        });

        register(null, {
            "build.gui": plugin
        });
    }
});
<|endoftext|>


<commit_before>/*global myCanvas, keyDownHandler, tapDownHandler,  SCREEN_X, SCREEN_Y, INTERLACE, PF, BL, P0, P1, M0, M1, sound, screen, reset_collision, get_collision, background, print_large, print_small, number_large, number_small, playfield, player0, player1, ball, missile0, missile1, requestAnimationFrame*/
/*jslint node: true */
/*jslint bitwise: true*/
'use strict';
document.getElementById(myCanvas);

var nemesis = [
    'XXXX    ',
    'XXXX    ',
    'XXXX    ',
    'XXXX    '];

var planet = [
    '                               XXX      ',
    '          XX                   XXXX     ',
    'XX                              XX      ',
    'XXX              XXXX                  X',
    'XX               XXXXX    XX            ',
    '                                        ',
    '                                        ',
    '                                        ',
    '                                        ',
    '                          XX            ',
    '   X                     XXXX           ',
    '   XXX                   XXXX           ',
    '                          XX            ',
    '                                        ',
    '      XXXX                XX            ',
    '                                        ',
    '                                        ',
    '                  XX                    ',
    '                 XXXX                   ',
    '                  XX      XX            ',
    '                               XXX      ',
    '                               XXXX     ',
    '   X                            XX      ',
    '  XXX                                   ',
    '   X                                    ',
    '                                        '];

var planet_scrolled = planet;

// Game states
var PAUSED = 1;
var READY = 0;
var PLAYING = 2;
var DONE = 3;

var blocky = [
    ' XXX',
    'XXX ',
    'XXX ',
    ' XXX',

    ' XX ',
    'XXXX',
    'XXXX',
    'X  X',

    'XXX ',
    ' XXX',
    ' XXX',
    'XXX ',

    'X  X',
    'XXXX',
    'XXXX',
    ' XX '];

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = (canvas.width / 2) * 1000;
var y = 0;
var dx = 200;
var thisTime = 0;
var lastTime = Date.now();
var dt = 1;

var game_state = READY;
var spacePressed = false;

var field_width = 24;
var NUM_LEVELS = 30;

var color_p0 = 15;
var color_p1 = 3;
var color_pf = 34;
var color_bk1 = 0;
var color_bk2 = 0;

var direction0 = 0;
var fire0 = false;

var anamation = 0.0;
var nemesis_y = 84.0;
var direction1 = -1.0;
var fire = 0;
var fire_x = (SCREEN_X / 2) - 8;
var fire_y = (SCREEN_Y / 2) + 2;
var fire_vx = 0;
var fire_vy = 0;

var retries = 0;
var level_number = 1;

var t = 0;
var pos_x = (SCREEN_X / 2) * 50;
var pos_y = (SCREEN_Y / 2) * 50;
var vel_x = 0;
var vel_y = 0;
var height0 = 4;
var direction0 = 0;

var jumping = 0;
var direction = 0;

var sound_duration = 0;

var sound_vol = 10;
var freq_1 = 31;
var freq_2 = 24;
var type_1 = 5;
var type_2 = 5;

var qty_stars = 30;
var my = [];
var mx = [];
var mi = [];
var star_twinkle_rate = 0;
var j = 0;
for (j = 0; j < qty_stars; j = j + 1) {
    mx.push(Math.random() * 159);
    my.push(Math.random() * 207);
    mi.push(Math.trunc(Math.random() * 3) + 1);
}
mx[0] = 0;
my[0] = 0;

document.addEventListener('keydown', keyDownHandler, false);
document.body.addEventListener('touchstart', tapDownHandler, false);
document.body.addEventListener('click', tapDownHandler, false);

function onPause() {
    sound_duration = 0;
    sound(1, 0.3, freq_1, type_1);
    sound(2, 0.3, freq_2, type_2);
    game_state = PAUSED;
}

function onResume() {
    game_state = PLAYING;
}

function onAmazonPlatformReady() {
    document.addEventListener("pause", onPause, false);
    document.addEventListener("resume", onResume, false);
}

document.addEventListener("amazonPlatformReady", onAmazonPlatformReady, false);

function tapDownHandler() {
    //fire0 = true;
    game_state = PLAYING;
}

function keyDownHandler(event) {
    var key = event.which || event.keyCode;
    if (key === 38) {
        //up arrow
        direction0 = 1;
    }
    if (key === 40) {
        //down arrow
        direction0 = 3;
    }

    if (key === 37) {
        //left arrow
        direction0 = 0;
    }
    if (key === 39) {
        //right arrow
        direction0 = 2;
    }

    if ((key === 13) || (key === 32)) {
        if (fire0 === false) {
            fire0 = true;
            fire_x = (SCREEN_X / 2) + 1;
            fire_y = (SCREEN_Y / 2) + 2;
            if (direction0 === 0) {
                vel_x -= 1;
                fire_vx = 1;
                fire_vy = 0;
            }
            if (direction0 === 1) {
                vel_y -= 1;
                fire_vx = 0;
                fire_vy = 1;
            }
            if (direction0 === 2) {
                vel_x += 1;
                fire_vx = -1;
                fire_vy = 1;
            }
            if (direction0 === 3) {
                vel_y += 1;
                fire_vx = 0;
                fire_vy = -1;
            }
        }
    }
}

function draw() {
    // drawing code
    var a,
        b,
        c,
        d,
        i;
    thisTime = Date.now();
    dt = thisTime - lastTime;
    lastTime = thisTime;

    dt = dt / 3;
    x += dx * dt;

    if (sound_duration > 1) {
        sound_duration -= 1;
    } else {
        sound(1, 0, freq_1, type_1);
        sound(2, 0, freq_2, type_2);
    }

    if (game_state === PAUSED) {
        print_large(2, 4 + 152, '   GAME', 2, color_p0);
        print_large(2, 4 + 168, '  PAUSED', 2, color_p0);
    } else {
        screen();
        reset_collision();

        background(0, SCREEN_Y, color_bk2);

        star_twinkle_rate += 1;
        for (j = 0; j < qty_stars; j = j + 1) {

            mx[j] += vel_x * dt / 50.0;
            if (mx[j] > SCREEN_X) {
                mx[j] -= SCREEN_X;
            }
            if (mx[j] < 0) {
                mx[j] += SCREEN_X;
            }
            my[j] += vel_y * dt / 50.0;
            if (my[j] > SCREEN_Y) {
                my[j] -= SCREEN_Y;
            }
            if (my[j] < 0) {
                my[j] += SCREEN_Y;
            }

            if (star_twinkle_rate > 10) {
                mi[j] = Math.trunc(Math.random() * 3) + 1;
            }

            missile1(mx[j], my[j], 1, 2, mi[j]);
        }
        if (star_twinkle_rate > 10) {
            star_twinkle_rate = 0;
        }

        // draw field
        for (i = 0; i < 26; i += 1) {
            b = (SCREEN_X - mx[0]) / 4;
            a = planet[i].slice(b, 39) + planet[i].slice(0, b);
            playfield(i * 8, 8, a, color_pf);
        }

        d = direction0 * 4;
        player0((SCREEN_X / 2), (SCREEN_Y / 2), blocky.slice(d, d + 4), 1, 2, 0, color_p0);

        if (fire0 === true) {
            fire_x += fire_vx;
            fire_y += fire_vy;
            if (fire_x < 0) {
                fire0 = false;
            }
            if (fire_x > SCREEN_X) {
                fire0 = false;
            }
            if (fire_y < 0) {
                fire0 = false;
            }
            if (fire_y > SCREEN_Y) {
                fire0 = false;
            }
            missile0(fire_x, fire_y, 2, 4, color_p0);
        }

    }
    //print_large(12, 4 + 102, 'LOST', 2, color_p0);
    //print_large(12, 4 + 118, 'SPACE', 2, color_p0);
    //print_large(12, 4 + 134, 'BABIES', 2, color_p0);
    requestAnimationFrame(draw);
}

draw();
<commit_msg>Working on firing logic<commit_after>/*global myCanvas, keyDownHandler, tapDownHandler,  SCREEN_X, SCREEN_Y, INTERLACE, PF, BL, P0, P1, M0, M1, sound, screen, reset_collision, get_collision, background, print_large, print_small, number_large, number_small, playfield, player0, player1, ball, missile0, missile1, requestAnimationFrame*/
/*jslint node: true */
/*jslint bitwise: true*/
'use strict';
document.getElementById(myCanvas);

var nemesis = [
    'XXXX    ',
    'XXXX    ',
    'XXXX    ',
    'XXXX    '];

var planet = [
    '                               XXX      ',
    '          XX                   XXXX     ',
    'XX                              XX      ',
    'XXX              XXXX                  X',
    'XX               XXXXX    XX            ',
    '                                        ',
    '                                        ',
    '                                        ',
    '                                        ',
    '                          XX            ',
    '   X                     XXXX           ',
    '   XXX                   XXXX           ',
    '                          XX            ',
    '                                        ',
    '      XXXX                XX            ',
    '                                        ',
    '                                        ',
    '                  XX                    ',
    '                 XXXX                   ',
    '                  XX      XX            ',
    '                               XXX      ',
    '                               XXXX     ',
    '   X                            XX      ',
    '  XXX                                   ',
    '   X                                    ',
    '                                        '];

var planet_scrolled = planet;

// Game states
var PAUSED = 1;
var READY = 0;
var PLAYING = 2;
var DONE = 3;

var blocky = [
    ' XXX',
    'XXX ',
    'XXX ',
    ' XXX',

    ' XX ',
    'XXXX',
    'XXXX',
    'X  X',

    'XXX ',
    ' XXX',
    ' XXX',
    'XXX ',

    'X  X',
    'XXXX',
    'XXXX',
    ' XX '];

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = (canvas.width / 2) * 1000;
var y = 0;
var dx = 200;
var thisTime = 0;
var lastTime = Date.now();
var dt = 1;

var game_state = READY;
var spacePressed = false;

var field_width = 24;
var NUM_LEVELS = 30;

var color_p0 = 15;
var color_p1 = 3;
var color_pf = 34;
var color_bk1 = 0;
var color_bk2 = 0;

var direction0 = 0;
var fire0 = false;

var anamation = 0.0;
var nemesis_y = 84.0;
var direction1 = -1.0;
var fire = 0;
var fire_x = (SCREEN_X / 2) - 8;
var fire_y = (SCREEN_Y / 2) + 2;
var fire_vx = 0;
var fire_vy = 0;

var retries = 0;
var level_number = 1;

var t = 0;
var pos_x = (SCREEN_X / 2) * 50;
var pos_y = (SCREEN_Y / 2) * 50;
var vel_x = 0;
var vel_y = 0;
var height0 = 4;
var direction0 = 0;

var jumping = 0;
var direction = 0;

var sound_duration = 0;

var sound_vol = 10;
var freq_1 = 31;
var freq_2 = 24;
var type_1 = 5;
var type_2 = 5;

var qty_stars = 30;
var my = [];
var mx = [];
var mi = [];
var star_twinkle_rate = 0;
var j = 0;
for (j = 0; j < qty_stars; j = j + 1) {
    mx.push(Math.random() * 159);
    my.push(Math.random() * 207);
    mi.push(Math.trunc(Math.random() * 3) + 1);
}
mx[0] = 0;
my[0] = 0;

document.addEventListener('keydown', keyDownHandler, false);
document.body.addEventListener('touchstart', tapDownHandler, false);
document.body.addEventListener('click', tapDownHandler, false);

function onPause() {
    sound_duration = 0;
    sound(1, 0.3, freq_1, type_1);
    sound(2, 0.3, freq_2, type_2);
    game_state = PAUSED;
}

function onResume() {
    game_state = PLAYING;
}

function onAmazonPlatformReady() {
    document.addEventListener("pause", onPause, false);
    document.addEventListener("resume", onResume, false);
}

document.addEventListener("amazonPlatformReady", onAmazonPlatformReady, false);

function tapDownHandler() {
    //fire0 = true;
    game_state = PLAYING;
}

function keyDownHandler(event) {
    var key = event.which || event.keyCode;
    if (key === 38) {
        //up arrow
        direction0 = 1;
    }
    if (key === 40) {
        //down arrow
        direction0 = 3;
    }

    if (key === 37) {
        //left arrow
        direction0 = 0;
    }
    if (key === 39) {
        //right arrow
        direction0 = 2;
    }

    if ((key === 13) || (key === 32)) {
        if (fire0 === false) {
            fire0 = true;
            fire_x = (SCREEN_X / 2) + 1;
            fire_y = (SCREEN_Y / 2) + 2;
            if (direction0 === 0) {
                vel_x -= 1;
                fire_vx = -1;
                fire_vy = 0;
            }
            if (direction0 === 1) {
                vel_y -= 1;
                fire_vx = 0;
                fire_vy = -1;
            }
            if (direction0 === 2) {
                vel_x += 1;
                fire_vx = 1;
                fire_vy = 0;
            }
            if (direction0 === 3) {
                vel_y += 1;
                fire_vx = 0;
                fire_vy = 1;
            }
        }
    }
}

function draw() {
    // drawing code
    var a,
        b,
        c,
        d,
        i;
    thisTime = Date.now();
    dt = thisTime - lastTime;
    lastTime = thisTime;

    dt = dt / 3;
    x += dx * dt;

    if (sound_duration > 1) {
        sound_duration -= 1;
    } else {
        sound(1, 0, freq_1, type_1);
        sound(2, 0, freq_2, type_2);
    }

    if (game_state === PAUSED) {
        print_large(2, 4 + 152, '   GAME', 2, color_p0);
        print_large(2, 4 + 168, '  PAUSED', 2, color_p0);
    } else {
        screen();
        reset_collision();

        background(0, SCREEN_Y, color_bk2);

        star_twinkle_rate += 1;
        for (j = 0; j < qty_stars; j = j + 1) {

            mx[j] += vel_x * dt / 50.0;
            if (mx[j] > SCREEN_X) {
                mx[j] -= SCREEN_X;
            }
            if (mx[j] < 0) {
                mx[j] += SCREEN_X;
            }
            my[j] += vel_y * dt / 50.0;
            if (my[j] > SCREEN_Y) {
                my[j] -= SCREEN_Y;
            }
            if (my[j] < 0) {
                my[j] += SCREEN_Y;
            }

            if (star_twinkle_rate > 10) {
                mi[j] = Math.trunc(Math.random() * 3) + 1;
            }

            missile1(mx[j], my[j], 1, 2, mi[j]);
        }
        if (star_twinkle_rate > 10) {
            star_twinkle_rate = 0;
        }

        // draw field
        for (i = 0; i < 26; i += 1) {
            b = (SCREEN_X - mx[0]) / 4;
            a = planet[i].slice(b, 39) + planet[i].slice(0, b);
            playfield(i * 8, 8, a, color_pf);
        }

        d = direction0 * 4;
        player0((SCREEN_X / 2), (SCREEN_Y / 2), blocky.slice(d, d + 4), 1, 2, 0, color_p0);

        if (fire0 === true) {
            fire_x += fire_vx;
            fire_y += fire_vy;
            if (fire_x < 0) {
                fire0 = false;
            }
            if (fire_x > SCREEN_X) {
                fire0 = false;
            }
            if (fire_y < 0) {
                fire0 = false;
            }
            if (fire_y > SCREEN_Y) {
                fire0 = false;
            }
            missile0(fire_x, fire_y, 2, 4, color_p0);
        }

    }
    //print_large(12, 4 + 102, 'LOST', 2, color_p0);
    //print_large(12, 4 + 118, 'SPACE', 2, color_p0);
    //print_large(12, 4 + 134, 'BABIES', 2, color_p0);
    requestAnimationFrame(draw);
}

draw();
<|endoftext|>


<commit_before>module.exports = {
  'enforce': function(f, msg) {
    if (!f()) {
      console.error("\u001b[31m" + msg + "\u001b[0m");
    }
  },

  'odd': function(x) {
    if ((x % 2) == 1) {
      return true;
    }
    return false;
  },

  'single': function(x) {
    return {'each': function(f) { return f(x); }};
  },

  'below': function(x) {
    return function(y) { return y < x; };
  }
}
<commit_msg>Added a few library functions<commit_after>module.exports = {
  'enforce': function(f, msg) {
    if (!f()) {
      console.error("\u001b[31m" + msg + "\u001b[0m");
    }
  },

  'odd': function(x) {
    if ((x % 2) == 1) {
      return true;
    }
    return false;
  },

  'single': function(x) {
    return {'each': function(f) { return f(x); }};
  },

  'below': function(x) {
    return function(y) { return y < x; };
  },

  'above': function(x) {
    return function(y) { return y > x; };
  },

  'equal': function(x) {
    return function(y) { return y === x; };
  },

  'sorted': function(x) {
  	return (function(direction) {
	    return this.reduce(function(prev, next, i, arr) {
	      if (direction === undefined)
	        return (direction = prev <= next ? 1 : -1) || true;
	      else
	        return (direction + 1 ?
	          (arr[i-1] <= next) :
	          (arr[i-1] >  next));
	    }) ? Number(direction) : false;
	  }).call(this);
  },

  'all': function(x) {
    return {'each': function(f) {
    	return x.every(f);
    }};
  },
}
<|endoftext|>


<commit_before>/*
  Copyright (c) 2007-2010 Alessandro Warth <awarth@cs.ucla.edu>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

// try to use StringBuffer instead of string concatenation to improve performance

function StringBuffer() {
  this.strings = []
  for (var idx = 0; idx < arguments.length; idx++)
    this.nextPutAll(arguments[idx])
}
StringBuffer.prototype.nextPutAll = function(s) { this.strings.push(s) }
StringBuffer.prototype.contents   = function()  { return this.strings.join("") }
String.prototype.writeStream      = function() { return new StringBuffer(this) }

// make Arrays print themselves sensibly

printOn = function(x, ws) {
  if (x === undefined || x === null)
    ws.nextPutAll("" + x)
  else if (x.constructor === Array) {
    ws.nextPutAll("[")
    for (var idx = 0; idx < x.length; idx++) {
      if (idx > 0)
        ws.nextPutAll(", ")
      printOn(x[idx], ws)
    }
    ws.nextPutAll("]")
  }
  else
    ws.nextPutAll(x.toString())
}

Array.prototype.toString = function() { var ws = "".writeStream(); printOn(this, ws); return ws.contents() }

// delegation

objectThatDelegatesTo = function(x, props) {
  var f = function() { }
  f.prototype = x
  var r = new f()
  for (var p in props)
    if (props.hasOwnProperty(p))
      r[p] = props[p]
  return r
}

// some reflective stuff

ownPropertyNames = function(x) {
  var r = []
  for (name in x)
    if (x.hasOwnProperty(name))
      r.push(name)
  return r
}

isImmutable = function(x) {
   return x === null || x === undefined || typeof x === "boolean" || typeof x === "number" || typeof x === "string"
}

String.prototype.digitValue  = function() { return this.charCodeAt(0) - "0".charCodeAt(0) }

isSequenceable = function(x) { return typeof x == "string" || x.constructor === Array }

// some functional programming stuff

Array.prototype.map = function(f) {
  var r = []
  for (var idx = 0; idx < this.length; idx++)
    r[idx] = f(this[idx])
  return r
}

Array.prototype.reduce = function(f, z) {
  var r = z
  for (var idx = 0; idx < this.length; idx++)
    r = f(r, this[idx])
  return r
}

Array.prototype.delimWith = function(d) {
  return this.reduce(
    function(xs, x) {
      if (xs.length > 0)
        xs.push(d)
      xs.push(x)
      return xs
    },
   [])
}

// Squeak's ReadStream, kind of

function ReadStream(anArrayOrString) {
  this.src = anArrayOrString
  this.pos = 0
}
ReadStream.prototype.atEnd = function() { return this.pos >= this.src.length }
ReadStream.prototype.next  = function() { return this.src.at(this.pos++) }

// escape characters

escapeStringFor = new Object()
for (var c = 0; c < 256; c++)
  escapeStringFor[c] = String.fromCharCode(c)
escapeStringFor["\\".charCodeAt(0)] = "\\\\"
escapeStringFor['"'.charCodeAt(0)]  = '\\"'
escapeStringFor["'".charCodeAt(0)]  = "\\'"
escapeStringFor["\r".charCodeAt(0)] = "\\r"
escapeStringFor["\n".charCodeAt(0)] = "\\n"
escapeStringFor["\t".charCodeAt(0)] = "\\t"
escapeChar = function(c) {
  var charCode = c.charCodeAt(0)
  return charCode > 255 ? String.fromCharCode(charCode) : escapeStringFor[charCode]
}

function unescape(s) {
  if (s.charAt(0) == '\\')
    switch (s.charAt(1)) {
      case '\\': return '\\'
      case 'r':  return '\r'
      case 'n':  return '\n'
      case 't':  return '\t'
      default:   return s.charAt(1)
    }
  else
    return s
}

String.prototype.toProgramString = function() {
  var ws = "\"".writeStream()
  for (var idx = 0; idx < this.length; idx++)
    ws.nextPutAll(escapeChar(this.charAt(idx)))
  ws.nextPutAll("\"")
  return ws.contents()
}

// C-style tempnam function

function tempnam(s) { return (s ? s : "_tmpnam_") + tempnam.n++ }
tempnam.n = 0

// unique tags for objects (useful for making "hash tables")

getTag = (function() {
  var numIdx = 0
  return function(x) {
    if (x === null || x === undefined)
      return x
    switch (typeof x) {
      case "boolean": return x == true ? "Btrue" : "Bfalse"
      case "string":  return "S" + x
      case "number":  return "N" + x
      default:        return x.hasOwnProperty("_id_") ? x._id_ : x._id_ = "R" + numIdx++
    }
  }
})()

<commit_msg>added support for \xHH and \uHHHH to escapeChar() and unescape()<commit_after>/*
  Copyright (c) 2007-2010 Alessandro Warth <awarth@cs.ucla.edu>

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

// try to use StringBuffer instead of string concatenation to improve performance

function StringBuffer() {
  this.strings = []
  for (var idx = 0; idx < arguments.length; idx++)
    this.nextPutAll(arguments[idx])
}
StringBuffer.prototype.nextPutAll = function(s) { this.strings.push(s) }
StringBuffer.prototype.contents   = function()  { return this.strings.join("") }
String.prototype.writeStream      = function() { return new StringBuffer(this) }

// make Arrays print themselves sensibly

printOn = function(x, ws) {
  if (x === undefined || x === null)
    ws.nextPutAll("" + x)
  else if (x.constructor === Array) {
    ws.nextPutAll("[")
    for (var idx = 0; idx < x.length; idx++) {
      if (idx > 0)
        ws.nextPutAll(", ")
      printOn(x[idx], ws)
    }
    ws.nextPutAll("]")
  }
  else
    ws.nextPutAll(x.toString())
}

Array.prototype.toString = function() { var ws = "".writeStream(); printOn(this, ws); return ws.contents() }

// delegation

objectThatDelegatesTo = function(x, props) {
  var f = function() { }
  f.prototype = x
  var r = new f()
  for (var p in props)
    if (props.hasOwnProperty(p))
      r[p] = props[p]
  return r
}

// some reflective stuff

ownPropertyNames = function(x) {
  var r = []
  for (name in x)
    if (x.hasOwnProperty(name))
      r.push(name)
  return r
}

isImmutable = function(x) {
   return x === null || x === undefined || typeof x === "boolean" || typeof x === "number" || typeof x === "string"
}

String.prototype.digitValue  = function() { return this.charCodeAt(0) - "0".charCodeAt(0) }

isSequenceable = function(x) { return typeof x == "string" || x.constructor === Array }

// some functional programming stuff

Array.prototype.map = function(f) {
  var r = []
  for (var idx = 0; idx < this.length; idx++)
    r[idx] = f(this[idx])
  return r
}

Array.prototype.reduce = function(f, z) {
  var r = z
  for (var idx = 0; idx < this.length; idx++)
    r = f(r, this[idx])
  return r
}

Array.prototype.delimWith = function(d) {
  return this.reduce(
    function(xs, x) {
      if (xs.length > 0)
        xs.push(d)
      xs.push(x)
      return xs
    },
   [])
}

// Squeak's ReadStream, kind of

function ReadStream(anArrayOrString) {
  this.src = anArrayOrString
  this.pos = 0
}
ReadStream.prototype.atEnd = function() { return this.pos >= this.src.length }
ReadStream.prototype.next  = function() { return this.src.at(this.pos++) }

// escape characters

String.prototype.pad = function(s, len) {
  var r = this
  while (r.length < len)
    r = s + r
  return r
}

escapeStringFor = new Object()
for (var c = 0; c < 128; c++)
  escapeStringFor[c] = String.fromCharCode(c)
escapeStringFor["'".charCodeAt(0)]  = "\\'"
escapeStringFor['"'.charCodeAt(0)]  = '\\"'
escapeStringFor["\\".charCodeAt(0)] = "\\\\"
escapeStringFor["\b".charCodeAt(0)] = "\\b"
escapeStringFor["\f".charCodeAt(0)] = "\\f"
escapeStringFor["\n".charCodeAt(0)] = "\\n"
escapeStringFor["\r".charCodeAt(0)] = "\\r"
escapeStringFor["\t".charCodeAt(0)] = "\\t"
escapeStringFor["\v".charCodeAt(0)] = "\\v"
escapeChar = function(c) {
  var charCode = c.charCodeAt(0)
  if (charCode < 128)
    return escapeStringFor[charCode]
  else if (128 <= charCode && charCode < 256)
    return "\\x" + charCode.toString(16).pad("0", 2)
  else
    return "\\u" + charCode.toString(16).pad("0", 4)
}

function unescape(s) {
  if (s.charAt(0) == '\\')
    switch (s.charAt(1)) {
      case "'":  return "'"
      case '"':  return '"'
      case '\\': return '\\'
      case 'b':  return '\b'
      case 'f':  return '\f'
      case 'n':  return '\n'
      case 'r':  return '\r'
      case 't':  return '\t'
      case 'v':  return '\v'
      case 'x':  return String.fromCharCode(parseInt(s.substring(2, 4), 16))
      case 'u':  return String.fromCharCode(parseInt(s.substring(2, 6), 16))
      default:   return s.charAt(1)
    }
  else
    return s
}

String.prototype.toProgramString = function() {
  var ws = '"'.writeStream()
  for (var idx = 0; idx < this.length; idx++)
    ws.nextPutAll(escapeChar(this.charAt(idx)))
  ws.nextPutAll('"')
  return ws.contents()
}

// C-style tempnam function

function tempnam(s) { return (s ? s : "_tmpnam_") + tempnam.n++ }
tempnam.n = 0

// unique tags for objects (useful for making "hash tables")

getTag = (function() {
  var numIdx = 0
  return function(x) {
    if (x === null || x === undefined)
      return x
    switch (typeof x) {
      case "boolean": return x == true ? "Btrue" : "Bfalse"
      case "string":  return "S" + x
      case "number":  return "N" + x
      default:        return x.hasOwnProperty("_id_") ? x._id_ : x._id_ = "R" + numIdx++
    }
  }
})()

<|endoftext|>


<commit_before>module.exports = function log() {
  for (const { value } of this){
    console.log(value)
  }
}
<commit_msg>update log to log individual elements as well as whole item of caller<commit_after>module.exports = function log() {
  console.log('iterator result: ', this)
  for (const value of this){
    console.log('iterated value: ', value)
  }
}
<|endoftext|>