<commit_before>"use strict"

var Readable = require("stream").Readable
var util = require("util")
var littleEndian = require("is-little-endian")

module.exports = writePLY

var SUFFIX = littleEndian ? "LE" : "BE"

var TYPE_DATA = {
  "char":   [ 1, "writeInt8" ],
  "uchar":  [ 1, "writeUInt8" ],
  "short":  [ 2, "writeInt16" + SUFFIX ],
  "ushort": [ 2, "writeUInt16" + SUFFIX ],
  "int":    [ 4, "writeInt32" + SUFFIX ],
  "uint":   [ 4, "writeUInt32" + SUFFIX ],
  "float":  [ 4, "writeFloat" + SUFFIX ],
  "double": [ 8, "writeDouble" + SUFFIX ]
}

var READER_STATE = {
  HEADER: 0,
  VERTEX: 1,
  FACE: 2,
  DONE: 3
}

function propertyType(t) {
  if(t instanceof Int8Array) {
    return "char"
  } else if(t instanceof Uint8Array) {
    return "uchar"
  } else if(t instanceof Int16Array) {
    return "short"
  } else if(t instanceof Uint16Array) {
    return "ushort"
  } else if(t instanceof Int32Array) {
    return "int"
  } else if(t instanceof Uint32Array) {
    return "uint"
  } else if(t instanceof Float32Array) {
    return "float"
  } else if(t instanceof Float64Array) {
    return "double"
  } else if(t instanceof Array) {
    if(typeof t[0] === "number") {
      for(var i=0; i<t.length; ++i) {
        if(t[i] !== t[i]>>0) {
          return "double"
        }
      }
      return "int"
    } else {
      var l = 0
      var subType = "int"
      for(var i=0; i<t.length; ++i) {
        l = Math.max(l, t[i].length)
        if(subType === "int") {
          subType = propertyType(t[i])
        }
      }
      if(l < 256) {
        return "list uchar " + subType
      } else if(l < 65536) {
        return "list ushort " + subType
      } else {
        return "list uint " + subType
      }
    }
  }
  throw new Error("Unknown type for property")
}

function createPropertyHeader(object, name, props, count, types) {
  var result = []
  result.push([ "element ", name, " ", count ].join(""))
  for(var i=0; i<props.length; ++i) {
    result.push(["property ", types[i], " ", props[i]].join(""))
  }
  return result.join("\n")
}

function flatten(obj, props) {
  var result = new Array(props.length)
  for(var i=0; i<props.length; ++i) {
    result[i] = obj[props[i]]
  }
  return result
}

function compileEmitFunctionAscii(types) {
  var code = ["this.push(["]
  for(var i=0; i<types.length; ++i) {
    var t = types[i].split(" ")
    if(t[0] === "list") {
      var localVar = "d" + i
      var localPrefix = "d" + i + "_"
      var loop = [ "var " + localVar + "=[]" ]
      var localN, localJ, localP
      for(var j=0; j<t.length; j+=3) {
        localN = localPrefix + "n" + j
        localJ = localPrefix + "j" + j
        localP = localPrefix + "p" + j

        if(j === 0) {
          loop.push(["var ", localP, "=data[", i, "][i]"].join(""))
        } else {
          loop.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
        }
        loop.push(["var ", localN, "=", localP, ".length"].join(""))
        loop.push([localVar, ".push(", localN, ")"].join(""))
        loop.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
      }
      loop.push([localVar, ".push(", localP, "[", localJ, "])"].join(""))
      for(var j=0; j<t.length; j+=3) {
        loop.push("}")
      }
      code.unshift(loop.join("\n"))
      if(i < types.length - 1) {
        code.push(localVar + ".join(' '),")
      } else {
        code.push(localVar + ".join(' ')")
      }
    } else {
      if(i < types.length - 1) {
        code.push(["data[", i, "][i],"].join(""))
      } else {
        code.push(["data[", i, "][i]"].join(""))
      }
    }
  }
  code.push("].join(' ')+'\\n','ascii')")
  return new Function("data", "i", code.join("\n"))
}

function compileEmitFunctionBinary(types) {
  var size = 0
  var variableSize = false
  for(var i=0; i<types.length; ++i) {
    var td = TYPE_DATA[types[i]]
    if(td) {
      size += td[0]
    } else {
      variableSize = true
    }
  }
  if(variableSize) {
    var code = [ "var n=" + size ]
    //First pass:  Compute the size of the buffer
    for(var i=0; i<types.length; ++i) {
      var t = types[i].split(" ")
      if(t[0] === "list") {
        var localPrefix = "d" + i + "_"
        var localN, localJ, localP
        for(var j=0; j<t.length; j+=3) {
          localN = localPrefix + "n" + j
          localJ = localPrefix + "j" + j
          localP = localPrefix + "p" + j
          if(j === 0) {
            code.push(["var ", localP, "=data[", i, "][i]"].join(""))
          } else {
            code.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
          }
          code.push(["var ", localN, "=", localP, ".length"].join(""))
          code.push(["n+=" + TYPE_DATA[t[j+1]][0]].join(""))

          if(j + 3 < t.length) {
            code.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
          } else {
            code.push(["n+=", localN, "*", TYPE_DATA[t[j+2]][0]].join(""))
          }
        }
        for(var j=3; j<t.length; j+=3) {
          code.push("}")
        }
      }
    }
    //Now allocate buffer
    code.push("var b=new Buffer(n),ptr=0")
    //Second pass: Fill in buffer
    for(var i=0; i<types.length; ++i) {
      var t = types[i].split(" ")
      if(t[0] === "list") {
        var localPrefix = "d" + i + "_"
        var localN, localJ, localP
        for(var j=0; j<t.length; j+=3) {
          localN = localPrefix + "n" + j
          localJ = localPrefix + "j" + j
          localP = localPrefix + "p" + j
          if(j === 0) {
            code.push(["var ", localP, "=data[", i, "][i]"].join(""))
          } else {
            code.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
          }
          code.push(["var ", localN, "=", localP, ".length"].join(""))
          code.push(["b.", TYPE_DATA[t[j+1]][1], "(", localN, ",ptr,true)"].join(""))
          code.push("ptr+=" + TYPE_DATA[t[j+1]][0])
          code.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
        }
        code.push(["b.", TYPE_DATA[t[t.length-1]][1], "(", localP, "[", localJ, "],ptr,true)"].join(""))
        code.push("ptr+=" + TYPE_DATA[t[t.length-1]][0])
        for(var j=0; j<t.length; j+=3) {
          code.push("}")
        }
      } else {
        code.push(["b.", TYPE_DATA[types[i]][1], "(ptr,data[", i, "][i],true)"].join(""))
      }
    }
    code.push("this.push(b)")
    return new Function("data", "i", code.join("\n"))
  } else {
    //Fixed size, type easy case
    var code = [ ["var b=new Buffer(", size, ")"].join("") ]
    var ptr = 0
    for(var i=0; i<types.length; ++i) {
      var td = TYPE_DATA[types[i]]
      code.push(["b.", td[1], "(data[", i, "][i],", ptr, ",true)"].join(""))
      ptr += td[0]
    }
    code.push("this.push(b)")
    return new Function("data", "i", code.join("\n"))
  }
}

var CACHED = {}

function getEmit(binary, types) {
  var typeSig = (binary ? "binary" : "ascii") + "&" + types.join()
  if(typeSig in CACHED) {
    return CACHED[typeSig]
  } else {
    var emit
    if(binary) {
      emit = compileEmitFunctionBinary(types)
    } else {
      emit = compileEmitFunctionAscii(types)
    }
    CACHED[typeSig] = emit
    return emit
  }
}

function PLYReadStream(header, vertex, emitVertex, vertexCount, face, emitFace, faceCount, options) {
  Readable.call(this, options)

  this._state = READER_STATE.HEADER

  this._header = header

  this._vertexData = vertex
  this._emitVertex = emitVertex
  this._vertexCount = vertexCount
  this._currentVertex = 0

  this._faceData = face
  this._emitFace = emitFace
  this._faceCount = faceCount
  this._currentFace = 0

  this._bops = bops
}

util.inherits(PLYReadStream, Readable)

PLYReadStream.prototype._read = function(sz) {
  switch(this._state) {
    case READER_STATE.HEADER:
      this.push(this._header, "ascii")
      this._state = READER_STATE.VERTEX
    break

    case READER_STATE.VERTEX:
      this._emitVertex(this._vertexData, this._currentVertex++)
      if(this._currentVertex >= this._vertexCount) {
        this._state = READER_STATE.FACE
      }
    break

    case READER_STATE.FACE:
      this._emitFace(this._faceData, this._currentFace++)
      if(this._currentFace >= this._faceCount) {
        this._state = READER_STATE.DONE
      }
    break

    case READER_STATE.DONE:
      this.push(null)
    break
  }
}

function getComments(data) {
  if(data.comments) {
    return data.comments.map(function(c) {
      return "comment " + c.replace(/\\/g, "\\").replace(/\n/g, "\\n")
    }).join("\n")
  }
  return "comment Generated by write-ply.js"
}

function writePLY(data, options) {
  options = options || {}
  var binary = !!options.binary
  var vertex = data.vertex || {}
  var vertexProps = Object.keys(vertex)
  var face = data.face || {}
  var faceProps = Object.keys(face)

  //Get vertex counts
  var vertexCount = 0
  if(vertexProps.length > 0) {
    vertexCount = vertex[vertexProps[0]].length
  }
  var faceCount = 0
  if(faceProps.length > 0) {
    faceCount = face[faceProps[0]].length
  }

  //Compute type for vertex/face formats
  var vertexTypes = new Array(vertexProps.length)
  for(var i=0; i<vertexProps.length; ++i) {
    vertexTypes[i] = propertyType(vertex[vertexProps[i]])
  }
  var faceTypes = new Array(faceProps.length)
  for(var i=0; i<faceProps.length; ++i) {
    faceTypes[i] = propertyType(face[faceProps[i]])
  }

  //Grab serialization methods
  var emitVertex = getEmit(binary, vertexTypes)
  var emitFace = getEmit(binary, faceTypes)

  //Evaluate PLY header
  var header = [
      "ply"
    , ["format ", binary ? (littleEndian ? "binary_little_endian" : "binary_big_endian") : "ascii", " 1.0"].join("")
    , getComments(data)
    , createPropertyHeader(vertex, "vertex", vertexProps, vertexCount, vertexTypes)
    , createPropertyHeader(face, "face", faceProps, faceCount, faceTypes)
    , "end_header\n"
  ].join("\n")

  //Create stream and return
  return new PLYReadStream(header
    , flatten(vertex, vertexProps)
    , emitVertex
    , vertexCount
    , flatten(face, faceProps)
    , emitFace
    , faceCount
    , options)
}<commit_msg>more bops stuff removed<commit_after>"use strict"

var Readable = require("stream").Readable
var util = require("util")
var littleEndian = require("is-little-endian")

module.exports = writePLY

var SUFFIX = littleEndian ? "LE" : "BE"

var TYPE_DATA = {
  "char":   [ 1, "writeInt8" ],
  "uchar":  [ 1, "writeUInt8" ],
  "short":  [ 2, "writeInt16" + SUFFIX ],
  "ushort": [ 2, "writeUInt16" + SUFFIX ],
  "int":    [ 4, "writeInt32" + SUFFIX ],
  "uint":   [ 4, "writeUInt32" + SUFFIX ],
  "float":  [ 4, "writeFloat" + SUFFIX ],
  "double": [ 8, "writeDouble" + SUFFIX ]
}

var READER_STATE = {
  HEADER: 0,
  VERTEX: 1,
  FACE: 2,
  DONE: 3
}

function propertyType(t) {
  if(t instanceof Int8Array) {
    return "char"
  } else if(t instanceof Uint8Array) {
    return "uchar"
  } else if(t instanceof Int16Array) {
    return "short"
  } else if(t instanceof Uint16Array) {
    return "ushort"
  } else if(t instanceof Int32Array) {
    return "int"
  } else if(t instanceof Uint32Array) {
    return "uint"
  } else if(t instanceof Float32Array) {
    return "float"
  } else if(t instanceof Float64Array) {
    return "double"
  } else if(t instanceof Array) {
    if(typeof t[0] === "number") {
      for(var i=0; i<t.length; ++i) {
        if(t[i] !== t[i]>>0) {
          return "double"
        }
      }
      return "int"
    } else {
      var l = 0
      var subType = "int"
      for(var i=0; i<t.length; ++i) {
        l = Math.max(l, t[i].length)
        if(subType === "int") {
          subType = propertyType(t[i])
        }
      }
      if(l < 256) {
        return "list uchar " + subType
      } else if(l < 65536) {
        return "list ushort " + subType
      } else {
        return "list uint " + subType
      }
    }
  }
  throw new Error("Unknown type for property")
}

function createPropertyHeader(object, name, props, count, types) {
  var result = []
  result.push([ "element ", name, " ", count ].join(""))
  for(var i=0; i<props.length; ++i) {
    result.push(["property ", types[i], " ", props[i]].join(""))
  }
  return result.join("\n")
}

function flatten(obj, props) {
  var result = new Array(props.length)
  for(var i=0; i<props.length; ++i) {
    result[i] = obj[props[i]]
  }
  return result
}

function compileEmitFunctionAscii(types) {
  var code = ["this.push(["]
  for(var i=0; i<types.length; ++i) {
    var t = types[i].split(" ")
    if(t[0] === "list") {
      var localVar = "d" + i
      var localPrefix = "d" + i + "_"
      var loop = [ "var " + localVar + "=[]" ]
      var localN, localJ, localP
      for(var j=0; j<t.length; j+=3) {
        localN = localPrefix + "n" + j
        localJ = localPrefix + "j" + j
        localP = localPrefix + "p" + j

        if(j === 0) {
          loop.push(["var ", localP, "=data[", i, "][i]"].join(""))
        } else {
          loop.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
        }
        loop.push(["var ", localN, "=", localP, ".length"].join(""))
        loop.push([localVar, ".push(", localN, ")"].join(""))
        loop.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
      }
      loop.push([localVar, ".push(", localP, "[", localJ, "])"].join(""))
      for(var j=0; j<t.length; j+=3) {
        loop.push("}")
      }
      code.unshift(loop.join("\n"))
      if(i < types.length - 1) {
        code.push(localVar + ".join(' '),")
      } else {
        code.push(localVar + ".join(' ')")
      }
    } else {
      if(i < types.length - 1) {
        code.push(["data[", i, "][i],"].join(""))
      } else {
        code.push(["data[", i, "][i]"].join(""))
      }
    }
  }
  code.push("].join(' ')+'\\n','ascii')")
  return new Function("data", "i", code.join("\n"))
}

function compileEmitFunctionBinary(types) {
  var size = 0
  var variableSize = false
  for(var i=0; i<types.length; ++i) {
    var td = TYPE_DATA[types[i]]
    if(td) {
      size += td[0]
    } else {
      variableSize = true
    }
  }
  if(variableSize) {
    var code = [ "var n=" + size ]
    //First pass:  Compute the size of the buffer
    for(var i=0; i<types.length; ++i) {
      var t = types[i].split(" ")
      if(t[0] === "list") {
        var localPrefix = "d" + i + "_"
        var localN, localJ, localP
        for(var j=0; j<t.length; j+=3) {
          localN = localPrefix + "n" + j
          localJ = localPrefix + "j" + j
          localP = localPrefix + "p" + j
          if(j === 0) {
            code.push(["var ", localP, "=data[", i, "][i]"].join(""))
          } else {
            code.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
          }
          code.push(["var ", localN, "=", localP, ".length"].join(""))
          code.push(["n+=" + TYPE_DATA[t[j+1]][0]].join(""))

          if(j + 3 < t.length) {
            code.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
          } else {
            code.push(["n+=", localN, "*", TYPE_DATA[t[j+2]][0]].join(""))
          }
        }
        for(var j=3; j<t.length; j+=3) {
          code.push("}")
        }
      }
    }
    //Now allocate buffer
    code.push("var b=new Buffer(n),ptr=0")
    //Second pass: Fill in buffer
    for(var i=0; i<types.length; ++i) {
      var t = types[i].split(" ")
      if(t[0] === "list") {
        var localPrefix = "d" + i + "_"
        var localN, localJ, localP
        for(var j=0; j<t.length; j+=3) {
          localN = localPrefix + "n" + j
          localJ = localPrefix + "j" + j
          localP = localPrefix + "p" + j
          if(j === 0) {
            code.push(["var ", localP, "=data[", i, "][i]"].join(""))
          } else {
            code.push(["var ", localP, "=", localPrefix, j-3, "[j", j-3, "]"].join(""))
          }
          code.push(["var ", localN, "=", localP, ".length"].join(""))
          code.push(["b.", TYPE_DATA[t[j+1]][1], "(", localN, ",ptr,true)"].join(""))
          code.push("ptr+=" + TYPE_DATA[t[j+1]][0])
          code.push(["for(var ", localJ, "=0;", localJ, "<", localN, ";++", localJ, "){"].join(""))
        }
        code.push(["b.", TYPE_DATA[t[t.length-1]][1], "(", localP, "[", localJ, "],ptr,true)"].join(""))
        code.push("ptr+=" + TYPE_DATA[t[t.length-1]][0])
        for(var j=0; j<t.length; j+=3) {
          code.push("}")
        }
      } else {
        code.push(["b.", TYPE_DATA[types[i]][1], "(ptr,data[", i, "][i],true)"].join(""))
      }
    }
    code.push("this.push(b)")
    return new Function("data", "i", code.join("\n"))
  } else {
    //Fixed size, type easy case
    var code = [ ["var b=new Buffer(", size, ")"].join("") ]
    var ptr = 0
    for(var i=0; i<types.length; ++i) {
      var td = TYPE_DATA[types[i]]
      code.push(["b.", td[1], "(data[", i, "][i],", ptr, ",true)"].join(""))
      ptr += td[0]
    }
    code.push("this.push(b)")
    return new Function("data", "i", code.join("\n"))
  }
}

var CACHED = {}

function getEmit(binary, types) {
  var typeSig = (binary ? "binary" : "ascii") + "&" + types.join()
  if(typeSig in CACHED) {
    return CACHED[typeSig]
  } else {
    var emit
    if(binary) {
      emit = compileEmitFunctionBinary(types)
    } else {
      emit = compileEmitFunctionAscii(types)
    }
    CACHED[typeSig] = emit
    return emit
  }
}

function PLYReadStream(header, vertex, emitVertex, vertexCount, face, emitFace, faceCount, options) {
  Readable.call(this, options)

  this._state = READER_STATE.HEADER

  this._header = header

  this._vertexData = vertex
  this._emitVertex = emitVertex
  this._vertexCount = vertexCount
  this._currentVertex = 0

  this._faceData = face
  this._emitFace = emitFace
  this._faceCount = faceCount
  this._currentFace = 0
}

util.inherits(PLYReadStream, Readable)

PLYReadStream.prototype._read = function(sz) {
  switch(this._state) {
    case READER_STATE.HEADER:
      this.push(this._header, "ascii")
      this._state = READER_STATE.VERTEX
    break

    case READER_STATE.VERTEX:
      this._emitVertex(this._vertexData, this._currentVertex++)
      if(this._currentVertex >= this._vertexCount) {
        this._state = READER_STATE.FACE
      }
    break

    case READER_STATE.FACE:
      this._emitFace(this._faceData, this._currentFace++)
      if(this._currentFace >= this._faceCount) {
        this._state = READER_STATE.DONE
      }
    break

    case READER_STATE.DONE:
      this.push(null)
    break
  }
}

function getComments(data) {
  if(data.comments) {
    return data.comments.map(function(c) {
      return "comment " + c.replace(/\\/g, "\\").replace(/\n/g, "\\n")
    }).join("\n")
  }
  return "comment Generated by write-ply.js"
}

function writePLY(data, options) {
  options = options || {}
  var binary = !!options.binary
  var vertex = data.vertex || {}
  var vertexProps = Object.keys(vertex)
  var face = data.face || {}
  var faceProps = Object.keys(face)

  //Get vertex counts
  var vertexCount = 0
  if(vertexProps.length > 0) {
    vertexCount = vertex[vertexProps[0]].length
  }
  var faceCount = 0
  if(faceProps.length > 0) {
    faceCount = face[faceProps[0]].length
  }

  //Compute type for vertex/face formats
  var vertexTypes = new Array(vertexProps.length)
  for(var i=0; i<vertexProps.length; ++i) {
    vertexTypes[i] = propertyType(vertex[vertexProps[i]])
  }
  var faceTypes = new Array(faceProps.length)
  for(var i=0; i<faceProps.length; ++i) {
    faceTypes[i] = propertyType(face[faceProps[i]])
  }

  //Grab serialization methods
  var emitVertex = getEmit(binary, vertexTypes)
  var emitFace = getEmit(binary, faceTypes)

  //Evaluate PLY header
  var header = [
      "ply"
    , ["format ", binary ? (littleEndian ? "binary_little_endian" : "binary_big_endian") : "ascii", " 1.0"].join("")
    , getComments(data)
    , createPropertyHeader(vertex, "vertex", vertexProps, vertexCount, vertexTypes)
    , createPropertyHeader(face, "face", faceProps, faceCount, faceTypes)
    , "end_header\n"
  ].join("\n")

  //Create stream and return
  return new PLYReadStream(header
    , flatten(vertex, vertexProps)
    , emitVertex
    , vertexCount
    , flatten(face, faceProps)
    , emitFace
    , faceCount
    , options)
}<|endoftext|>


<commit_before>import createRenderer from "../index.js";
import createContext from "pex-context";
import createGUI from "pex-gui";
import { mat4, quat, vec3 } from "pex-math";
import random from "pex-random";
import { cube, sphere } from "primitive-geometry";
import cosineGradient from "cosine-gradient";

const State = {
  sunPosition: [0, 5, -5],
  elevation: 65,
  azimuth: 0,
  mie: 0.000021,
  elevationMat: mat4.create(),
  rotationMat: mat4.create(),
};
random.seed(10);

// Utils
const scheme = [
  [0.0, 0.5, 0.5],
  [0.0, 0.5, 0.5],
  [0.0, 0.5, 0.333],
  [0.0, 0.5, 0.667],
];

// Standard Normal constiate using Box-Muller transform.
// http://stackoverflow.com/a/36481059
function randnBM() {
  const u = 1 - Math.random(); // Subtraction to flip [0, 1) to (0, 1].
  const v = 1 - Math.random();
  return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
}

function rand() {
  return (Math.random() * 2 - 1) * 3;
}

const gradient = cosineGradient(scheme[0], scheme[1], scheme[2], scheme[3]);

// Start
const ctx = createContext();
ctx.gl.getExtension("EXT_shader_texture_lod");
ctx.gl.getExtension("OES_standard_derivatives");
ctx.gl.getExtension("WEBGL_draw_buffers");
ctx.gl.getExtension("WEBGL_depth_texture");
ctx.gl.getExtension("OES_texture_float");

const renderer = createRenderer(ctx);

const gui = createGUI(ctx);
gui.addFPSMeeter();

let frameNumber = 0;
let debugOnce = false;

// Camera
const cameraEntity = renderer.entity([
  renderer.postProcessing({
    ssao: true,
    ssaoRadius: 4,
    dof: true,
    dofAperture: 1,
    dofFocusDistance: 5,
    fxaa: true,
  }),
  renderer.camera({
    fov: Math.PI / 3,
    aspect: ctx.gl.drawingBufferWidth / ctx.gl.drawingBufferHeight,
    exposure: 2,
  }),
  renderer.orbiter({ position: [0, 3, 8] }),
]);
renderer.add(cameraEntity);

// Meshes
const floorEntity = renderer.entity([
  renderer.transform({
    position: [0, -0.3, 0],
  }),
  renderer.geometry(cube({ sx: 14, sy: 0.02, sz: 14 })),
  renderer.material({
    baseColor: [1, 1, 1, 1],
    castShadows: true,
    receiveShadows: true,
  }),
]);
renderer.add(floorEntity);

let instanced = true;
const geom = cube({ sx: 0.2, sy: 0.5 + Math.random(), sz: 0.2 });
const offsets = [];
const scales = [];
const colors = [];
for (let i = 0; i < 1000; i++) {
  const x = (randnBM() * 8) / 3;
  const z = (randnBM() * 8) / 3;
  const y = 2 * random.noise2(x / 2, z / 2) + random.noise2(2 * x, 2 * z);
  const s = Math.max(0.0, 3.0 - Math.sqrt(x * x + z * z) / 2);
  const c = random.float(0.7, 0.9);
  offsets.push([x, y, z]);
  scales.push([1, s, 1]);
  colors.push([c, c, c, 1]);
}
if (instanced) {
  geom.offsets = { buffer: ctx.vertexBuffer(offsets), divisor: 1 };
  geom.scales = { buffer: ctx.vertexBuffer(scales), divisor: 1 };
  geom.instances = offsets.length;
  renderer.add(
    renderer.entity([
      renderer.geometry(geom),
      renderer.transform({}),
      renderer.material({
        baseColor: colors[0],
        rougness: 0.7,
        metallic: 0.0,
        castShadows: true,
        receiveShadows: true,
      }),
    ])
  );
} else {
  offsets.forEach((offset, i) => {
    renderer.add(
      renderer.entity([
        renderer.geometry(geom),
        renderer.transform({
          position: offset,
          scale: scales[i],
        }),
        renderer.material({
          baseColor: colors[i],
          rougness: 0.7,
          metallic: 0.0,
          castShadows: true,
          receiveShadows: true,
        }),
      ])
    );
  });
}

const sphereGeometry = sphere({ radius: 0.2 + Math.random() * 0.25 });
for (let i = 0; i < 100; i++) {
  const x = (rand() * 8) / 3;
  const z = (rand() * 8) / 3;
  const y = 2 * random.noise2(x / 2, z / 2) + random.noise2(2 * x, 2 * z);
  const s = Math.max(0.0, 3.0 - Math.sqrt(x * x + z * z) / 2);
  renderer.add(
    renderer.entity([
      renderer.geometry(sphereGeometry),
      renderer.transform({
        position: [x, y, z],
        scale: [s, s, s],
      }),
      renderer.material({
        baseColor: gradient(Math.random()).concat(1),
        rougness: 0.91,
        metallic: 0.0,
        castShadows: true,
        receiveShadows: true,
      }),
    ])
  );
}

// Lights
const sunDir = vec3.normalize([1, -1, 1]);
const sunPosition = vec3.addScaled([0, 0, 0], sunDir, -2);
const sunLight = renderer.directionalLight({
  color: [1, 1, 1, 1],
  intensity: 2,
  castShadows: true,
  bias: 0.01,
});
const sunTransform = renderer.transform({
  position: [2, 2, 2],
  rotation: quat.fromTo([0, 0, 1], vec3.normalize([-1, -1, -1]), [0, 1, 0]),
});
const sunEntity = renderer.entity([sunTransform, sunLight]);
renderer.add(sunEntity);

gui.addTexture2D("Shadow Map", sunLight._shadowMap);

const skyboxCmp = renderer.skybox({
  sunPosition,
});
const reflectionProbeCmp = renderer.reflectionProbe();
const skyEntity = renderer.entity([skyboxCmp, reflectionProbeCmp]);
renderer.add(skyEntity);

const pointLightEnt = renderer.entity([
  renderer.transform({
    position: [2, 2, 2],
  }),
  renderer.geometry(sphere({ radius: 0.2 })),
  renderer.material({
    baseColor: [1, 0, 0, 1],
    emissiveColor: [1, 0, 0, 1],
  }),
  renderer.pointLight({
    castShadows: true,
    color: [1, 0, 0, 1],
    intensity: 5,
  }),
]);
renderer.add(pointLightEnt);

const areaLightColor = [0, 1, 0, 1];
const areaLightEntity = renderer.entity([
  renderer.transform({
    position: [5, 2, 0],
    scale: [2, 5, 0.1],
    rotation: quat.fromTo(quat.create(), [0, 0, 1], [-1, 0, 0], [0, 1, 0]),
  }),
  renderer.geometry(cube({ sx: 1 })),
  renderer.material({
    emissiveColor: areaLightColor,
    baseColor: [0, 0, 0, 1],
    metallic: 1.0,
    roughness: 0.74,
  }),
  renderer.areaLight({
    intensity: 5,
    color: areaLightColor,
  }),
]);
renderer.add(areaLightEntity);

// GUI
gui.addParam(
  "AreaLight Size",
  areaLightEntity.transform,
  "scale",
  { min: 0, max: 5 },
  (value) => {
    areaLightEntity.transform.set({ scale: [value[0], value[1], value[2]] });
  }
);
gui.addParam(
  "AreaLight Intensity",
  areaLightEntity.getComponent("AreaLight"),
  "intensity",
  { min: 0, max: 5 }
);
gui.addParam("AreaLight", areaLightEntity.getComponent("AreaLight"), "color", {
  type: "color",
});

function updateSunPosition() {
  mat4.identity(State.elevationMat);
  mat4.identity(State.rotationMat);
  mat4.rotate(State.elevationMat, (State.elevation / 180) * Math.PI, [0, 0, 1]);
  mat4.rotate(State.rotationMat, (State.azimuth / 180) * Math.PI, [0, 1, 0]);

  const sunPosition = [2, 0, 0];
  vec3.multMat4(sunPosition, State.elevationMat);
  vec3.multMat4(sunPosition, State.rotationMat);

  const dir = vec3.normalize(vec3.sub([0, 0, 0], sunPosition));
  sunTransform.set({
    position: sunPosition,
    rotation: quat.fromTo(sunTransform.rotation, [0, 0, 1], dir, [0, 1, 0]),
  });
  skyboxCmp.set({ sunPosition });
  reflectionProbeCmp.set({ dirty: true });
}
gui.addParam(
  "Sun Elevation",
  State,
  "elevation",
  { min: -90, max: 180 },
  updateSunPosition
);

updateSunPosition();

window.addEventListener("keydown", ({ key }) => {
  if (key === "d") debugOnce = true;
});

ctx.frame(() => {
  ctx.debug(frameNumber++ === 1);
  ctx.debug(debugOnce);
  debugOnce = false;
  renderer.draw();

  gui.draw();

  window.dispatchEvent(new CustomEvent("pex-screenshot"));
});
<commit_msg>feat(examples/blocks): port shadows example to ecs<commit_after>import createRenderer from "../index.js";
import createContext from "pex-context";
import createGUI from "pex-gui";
import { mat4, quat, vec3 } from "pex-math";
import random from "pex-random";
import { cube, sphere } from "primitive-geometry";
import cosineGradient from "cosine-gradient";

const State = {
  sunPosition: [0, 5, -5],
  elevation: 65,
  azimuth: 0,
  mie: 0.000021,
  elevationMat: mat4.create(),
  rotationMat: mat4.create(),
};
random.seed(10);

// Utils
const scheme = [
  [0.0, 0.5, 0.5],
  [0.0, 0.5, 0.5],
  [0.0, 0.5, 0.333],
  [0.0, 0.5, 0.667],
];

// Standard Normal constiate using Box-Muller transform.
// http://stackoverflow.com/a/36481059
function randnBM() {
  const u = 1 - Math.random(); // Subtraction to flip [0, 1) to (0, 1].
  const v = 1 - Math.random();
  return Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
}

function rand() {
  return (Math.random() * 2 - 1) * 3;
}

const gradient = cosineGradient(scheme[0], scheme[1], scheme[2], scheme[3]);

// Start
const ctx = createContext({
  type: "webgl",
});

const renderer = createRenderer(ctx);
window.renderer = renderer;

function aabbToString(aabb) {
  if (!aabb) return "[]";
  return `[${aabb[0].map((f) => f.toFixed(0.1))} .. ${aabb[1].map((f) =>
    f.toFixed(0.1)
  )}]`;
}

function debugScene() {
  let s = "";
  renderer.entities.forEach((e, i) => {
    let pad = "";
    let transform = e.transform;
    while (transform) {
      pad += "--";
      transform = transform.parent;
    }
    let bbox = aabbToString(e.transform?.worldBounds);
    s += `${pad} ${i} ${e.name} ${Object.keys(e).join(" | ")} | ${bbox} \n`;
  });
  console.log(s);
  console.log("renderer.entities", renderer.entities);
}

const gui = createGUI(ctx);
gui.addFPSMeeter();
gui.addButton("Debug scene", debugScene);

let frameNumber = 0;
let debugOnce = false;

// Camera
const cameraEntity = renderer.entity({
  // renderer.postProcessing({
  //   ssao: true,
  //   ssaoRadius: 4,
  //   dof: true,
  //   dofAperture: 1,
  //   dofFocusDistance: 5,
  //   fxaa: true,
  // }),
  transform: renderer.transform(),
  camera: renderer.camera({
    fov: Math.PI / 3,
    aspect: ctx.gl.drawingBufferWidth / ctx.gl.drawingBufferHeight,
    exposure: 2,
  }),
  orbiter: renderer.orbiter({
    position: [0, 3, 8],
    element: ctx.gl.canvas,
  }),
});
renderer.add(cameraEntity);

// Meshes
const floorEntity = renderer.entity({
  transform: renderer.transform({
    position: [0, -0.3, 0],
  }),
  geometry: renderer.geometry(cube({ sx: 14, sy: 0.02, sz: 14 })),
  material: renderer.material({
    baseColor: [1, 1, 1, 1],
    // castShadows: true,
    // receiveShadows: true,
    depthTest: true,
    depthWrite: true,
    // unlit: true,
    roughness: 1,
    metallic: 1,
  }),
});
renderer.add(floorEntity);

let instanced = true;
const geom = cube({ sx: 0.2, sy: 0.5 + Math.random(), sz: 0.2 });
const offsets = [];
const scales = [];
const colors = [];
for (let i = 0; i < 1000; i++) {
  const x = (randnBM() * 8) / 3;
  const z = (randnBM() * 8) / 3;
  const y = 2 * random.noise2(x / 2, z / 2) + random.noise2(2 * x, 2 * z);
  const s = Math.max(0.0, 3.0 - Math.sqrt(x * x + z * z) / 2);
  const c = random.float(0.7, 0.9);
  offsets.push([x, y, z]);
  scales.push([1, s, 1]);
  colors.push([c, c, c, 1]);
}
if (instanced) {
  geom.offsets = { buffer: ctx.vertexBuffer(offsets), divisor: 1 };
  geom.scales = { buffer: ctx.vertexBuffer(scales), divisor: 1 };
  geom.instances = offsets.length;
  const ent = renderer.entity({
    geometry: renderer.geometry(geom),
    transform: renderer.transform({}),
    material: renderer.material({
      baseColor: colors[0],
      rougness: 0.7,
      metallic: 0.0,
      castShadows: true,
      receiveShadows: true,
    }),
  });
  renderer.add(ent); //TODO
} else {
  offsets.forEach((offset, i) => {
    const ent = renderer.entity({
      geometry: renderer.geometry(geom),
      transform: renderer.transform({
        position: offset,
        scale: scales[i],
      }),
      material: renderer.material({
        baseColor: colors[i],
        rougness: 0.7,
        metallic: 0.0,
        castShadows: true,
        receiveShadows: true,
      }),
    });
    renderer.add(ent); //TODO:
  });
}

const sphereGeometry = sphere({ radius: 0.2 + Math.random() * 0.25 });
for (let i = 0; i < 100; i++) {
  const x = (rand() * 8) / 3;
  const z = (rand() * 8) / 3;
  const y = 2 * random.noise2(x / 2, z / 2) + random.noise2(2 * x, 2 * z);
  const s = Math.max(0.0, 3.0 - Math.sqrt(x * x + z * z) / 2);
  const ent = renderer.entity({
    geometry: renderer.geometry(sphereGeometry),
    transform: renderer.transform({
      position: [x, y, z],
      scale: [s, s, s],
    }),
    material: renderer.material({
      baseColor: gradient(Math.random()).concat(1),
      rougness: 0.91,
      metallic: 0.0,
      castShadows: true,
      receiveShadows: true,
    }),
  });
  renderer.add(ent); //TODO:
}

// Lights
const sunDir = vec3.normalize([1, -1, 1]);
const sunPosition = vec3.addScaled([0, 0, 0], sunDir, -2);
const sunLight = renderer.directionalLight({
  color: [1, 1, 1, 2],
  intensity: 2, //TODO: not working light intensity
  castShadows: true,
  bias: 0.1,
});
const sunTransform = renderer.transform({
  position: [0.1, 2, 0.1],
  rotation: quat.fromTo([0, 0, 1], [0, 0, 1], vec3.normalize([-1, -1, -1])),
});
const sunEntity = renderer.entity({
  transform: sunTransform,
  directionalLight: sunLight,
});
renderer.add(sunEntity);

const skyboxCmp = renderer.skybox({
  sunPosition,
});
const reflectionProbeCmp = renderer.reflectionProbe();
const skyEntity = renderer.entity({
  skybox: skyboxCmp,
  reflectionProbe: reflectionProbeCmp,
});
renderer.add(skyEntity);

const pointLightEnt = renderer.entity({
  transform: renderer.transform({
    position: [2, 2, 2],
  }),
  // geometry: renderer.geometry(sphere({ radius: 0.2 })),
  material: renderer.material({
    baseColor: [1, 0, 0, 1],
    emissiveColor: [1, 0, 0, 1],
  }),
  pointLight: renderer.pointLight({
    // castShadows: true,
    color: [1, 0, 0, 1],
    intensity: 5,
  }),
});
// renderer.add(pointLightEnt);

const areaLightColor = [0, 1, 0, 1];
const areaLightEntity = renderer.entity({
  transform: renderer.transform({
    position: [5, 2, 0],
    scale: [2, 5, 0.1],
    rotation: quat.fromTo(quat.create(), [0, 0, 1], [-1, 0, 0], [0, 1, 0]),
  }),
  // geometry: renderer.geometry(cube({ sx: 1 })),
  material: renderer.material({
    emissiveColor: areaLightColor,
    baseColor: [0, 0, 0, 1],
    metallic: 1.0,
    roughness: 0.74,
  }),
  areaLight: renderer.areaLight({
    intensity: 5,
    color: areaLightColor,
  }),
});
// renderer.add(areaLightEntity);

// GUI
gui.addParam(
  "AreaLight Size",
  areaLightEntity.transform,
  "scale",
  { min: 0, max: 5 },
  (value) => {
    areaLightEntity.transform.set({ scale: [value[0], value[1], value[2]] });
  }
);
gui.addParam("AreaLight Intensity", areaLightEntity.areaLight, "intensity", {
  min: 0,
  max: 5,
});
gui.addParam("AreaLight", areaLightEntity.areaLight, "color", {
  type: "color",
});

function updateSunPosition() {
  mat4.identity(State.elevationMat);
  mat4.identity(State.rotationMat);
  mat4.rotate(State.elevationMat, (State.elevation / 180) * Math.PI, [0, 0, 1]);
  mat4.rotate(State.rotationMat, (State.azimuth / 180) * Math.PI, [0, 1, 0]);

  const sunPosition = [2, 0, 0];
  vec3.multMat4(sunPosition, State.elevationMat);
  vec3.multMat4(sunPosition, State.rotationMat);

  const dir = vec3.normalize(vec3.sub([0, 0, 0], sunPosition));
  // TODO:
  // sunTransform.set({
  //   position: sunPosition,
  //   rotation: quat.fromTo(sunTransform.rotation, [0, 0, 1], dir, [0, 1, 0]),
  // });
  // skyboxCmp.set({ sunPosition });
  // reflectionProbeCmp.set({ dirty: true });
}
gui.addParam(
  "Sun Elevation",
  State,
  "elevation",
  { min: -90, max: 180 },
  updateSunPosition
);

updateSunPosition();

window.addEventListener("keydown", ({ key }) => {
  if (key === "d") debugOnce = true;
});

renderer.addSystem(renderer.geometrySystem());
renderer.addSystem(renderer.transformSystem());
renderer.addSystem(renderer.cameraSystem());
renderer.addSystem(renderer.skyboxSystem());
renderer.addSystem(renderer.reflectionProbeSystem());
renderer.addSystem(renderer.renderSystem());

let shadowMapPreview;

ctx.frame(() => {
  ctx.debug(frameNumber++ === 1);
  ctx.debug(debugOnce);
  debugOnce = false;
  renderer.draw();

  if (sunLight._shadowMap && !shadowMapPreview) {
    shadowMapPreview = gui.addTexture2D("Shadow Map", sunLight._shadowMap); //TODO
  }

  gui.draw();

  window.dispatchEvent(new CustomEvent("pex-screenshot"));
});
<|endoftext|>


<commit_before>import commander from 'commander';
import { exists, readdir, readFile, writeFile } from 'mz/fs';
import path from 'path';

import downloadFile from './downloadFile';
import run from './run';

export default function cli() {
  let project = null;
  commander
    .arguments('<project>')
    .description('Run decaffeinate on one of the sample projects.')
    .action(projectArg => project = projectArg)
    .option('--publish',
      `Push the resulting repository to the decaffeinate fork. The
           current git user must have permissions to do so.`)
    .parse(process.argv);

  runCli(project, commander.publish);
}

async function runCli(project, shouldPublish) {
  try {
    if (project === 'all') {
      await testAllProjects(shouldPublish);
    } else {
      await testProject(project, shouldPublish);
    }
  } catch (e) {
    process.exitCode = 1;
    console.error(`ERROR: ${e.message}`);
  }
}

async function testAllProjects(shouldPublish) {
  let projectNames = await readdir('./examples');
  console.log(`Processing all projects: ${projectNames.join(', ')}`);
  for (let project of projectNames) {
    console.log(`Processing project ${project}...`);
    await testProject(project, shouldPublish);
  }
  console.log(`Successfully processed all projects: ${projectNames.join(', ')}`);
}

async function testProject(project, shouldPublish) {
  let originalCwd = process.cwd();
  let exampleDir = path.resolve(`./examples/${project}`);
  if (!await exists(exampleDir)) {
    throw new Error(`Unknown project: ${project}`);
  }

  let config = require(`../examples/${project}/config`).default;

  let suffix = Math.floor(Math.random() * 1000000000000);
  let repoDir = `./tmp-projects/${project}-${suffix}`;
  await run(`mkdir ${repoDir}`);

  // As a special case, allow an example consisting of multiple project (like
  // all CoffeeScript projects in the atom org). In this case, we make a fresh
  // repo with the contents of other cloned repos.
  if (config.isMultiProject) {
    for (let {url, name} of config.cloneRepos) {
      await run(`git clone --depth=50 ${url} ${repoDir}/${name}`);
      await run(`rm -rf ${repoDir}/${name}/.git`);
    }
  } else {
    let cloneSuffix = config.branch ? `--branch ${config.branch}` : '';
    await run(`git clone --depth=50 ${config.cloneUrl} ${repoDir} ${cloneSuffix}`);
  }

  if (config.useDefaultConfig) {
    await run(`cp -R ./default-config/. ${repoDir}`);
  }
  if (await exists(`${exampleDir}/bulk-decaffeinate.config.js`)) {
    await run(`cp ${exampleDir}/bulk-decaffeinate.config.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/.eslintrc.js`)) {
    await run(`cp ${exampleDir}/.eslintrc.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/babelrc`)) {
    await run(`cp ${exampleDir}/babelrc ${repoDir}/.babelrc`);
  }
  if (await exists(`${exampleDir}/package.json`)) {
    await run(`cp ${exampleDir}/package.json ${repoDir}`);
  }

  process.chdir(repoDir);

  if (config.isMultiProject) {
    await run(`git init`);
    await run(`git add -A`);
    await run(`git commit --no-verify -m "Initial commit"`);
  }

  if (shouldPublish) {
    await run(`git remote add fork ${config.forkUrl}`);
    await run('git fetch --depth=50 fork');
    // If we're using a custom branch/ref, it may not be valid to push to it, so
    // skip this step. (Currently this fits all use cases, but it can be made
    // more flexible later if necessary.)
    if (!config.branch && !config.isMultiProject) {
      await run('git push fork');
    }
  }

  if (await exists(`${exampleDir}/.gitignore_extension`)) {
    await run(`cat ${exampleDir}/.gitignore_extension >> .gitignore`);
  }

  await run('npm install');
  let dependencies = getDependencies(config);
  if (dependencies.length > 0) {
    await run(`npm install --save-dev --save-exact ${dependencies.join(' ')}`);
  }
  await run('git add -A');
  await run('git commit --no-verify -m "Add dependencies and config to prepare for decaffeinate"');

  if (config.beforeDecaffeinateScript) {
    await run(config.beforeDecaffeinateScript);
  }

  let conversionResult = await checkConversion(config);
  if (!conversionResult.passed) {
    await run('git add -A');
    await run('git commit --no-verify -m "Save decaffeinate error details"');

    await run('bulk-decaffeinate convert --skip-verify -p decaffeinate-successful-files.txt');
  } else {
    await run('bulk-decaffeinate convert --skip-verify');
  }

  await run('bulk-decaffeinate clean');
  // Make the patch its own commit after everything else so it's easier to
  // iterate on.
  if (await exists(`${exampleDir}/decaffeinate.patch`)) {
    await run(`git apply ${exampleDir}/decaffeinate.patch`);
    await run('git add -A');
    await run('git commit --no-verify -m "Modify the build to work with JavaScript"');
  }
  let testResult = await runTests(config);

  await downloadFile(getConversionResultBadgeUrl(conversionResult), './conversion-status.svg');
  await downloadFile(getTestResultBadgeUrl(testResult), './test-status.svg');
  await writeFile('./README.md', getReadme(project, conversionResult, testResult));
  await run('git add -A');
  await run('git commit --no-verify -m "Update README and badges with decaffeinate results"');

  if (shouldPublish) {
    await run('git push fork HEAD:decaffeinate -f');

    await run('git checkout --orphan gh-pages');
    await run('git rm --cached -r .');
    await run('git add conversion-status.svg');
    await run('git add test-status.svg');
    await run('git commit --no-verify -m "Add status SVGs to gh-pages branch"');
    await run('git push fork HEAD:gh-pages -f');
  }

  process.chdir(originalCwd);
}

const DEFAULT_PACKAGES = [
  'babel-cli',
  'babel-polyfill',
  'babel-preset-env',
  'babel-register',
  'eslint',
  'eslint-config-airbnb-base',
  'eslint-plugin-import',
];

function getDependencies(config) {
  let dependencies = [];
  if (config.useDefaultConfig) {
    dependencies.push(...DEFAULT_PACKAGES);
  }
  if (config.extraDependencies) {
    dependencies.push(...config.extraDependencies);
  }
  return dependencies;
}

async function checkConversion(config) {
  // To reduce build times, skip the check step if we expect success. If there
  // is a problem later, it will end up as a crash and the build will fail.
  if (config.expectConversionSuccess) {
    return {
      passed: true,
    };
  }
  await run('bulk-decaffeinate check');
  let hasErrorFile = await exists('./decaffeinate-errors.log');
  if (hasErrorFile) {
    let results = JSON.parse((await readFile('decaffeinate-results.json')).toString());
    let numErrors = results.filter(result => result.error).length;
    let numTotal = results.length;
    if (config.expectConversionSuccess) {
      process.exitCode = 1;
    }
    return {
      passed: false,
      numErrors,
      numTotal,
    };
  }
  return {
    passed: true,
  };
}

async function runTests(config) {
  if (config.skipTests) {
    console.log('Skipping tests for this project.');
    return 'SKIPPED';
  }
  try {
    if (config.testCommands) {
      for (let command of config.testCommands) {
        await run(command);
      }
    } else {
      await run('npm test');
    }
    return 'PASSED';
  } catch (e) {
    if (config.expectTestSuccess) {
      process.exitCode = 1;
    }
    return 'FAILED';
  }
}

function getReadme(project, conversionResult, testResult) {
  let jobId = process.env.TRAVIS_JOB_ID;
  let jobMessage = jobId ?
    `[Travis logs](https://travis-ci.org/decaffeinate/decaffeinate-example-builder/jobs/${jobId})` :
    '';
  return `\
# decaffeinate fork of ${project}

![Conversion Status](https://decaffeinate-examples.github.io/${project}/conversion-status.svg)
![Test Status](https://decaffeinate-examples.github.io/${project}/test-status.svg)

${jobMessage}

## Conversion results

${getConversionResultDescription(conversionResult)}

## Test results

${getTestResultDescription(testResult)}

## About this repository

This repository was generated automatically by the [decaffeinate-examples]
project using the [decaffeinate] tool.

[decaffeinate-examples]: https://github.com/decaffeinate/decaffeinate-examples
[decaffeinate]: https://github.com/decaffeinate/decaffeinate
`;
}

function getConversionResultBadgeUrl(conversionResult) {
  if (conversionResult.passed) {
    return getBadgeUrl('decaffeinate conversion', 'success', 'brightgreen');
  } else {
    return getBadgeUrl(
      'decaffeinate conversion',
      `${conversionResult.numErrors}/${conversionResult.numTotal} failed`,
      'red'
    );
  }
}

function getTestResultBadgeUrl(testResult) {
  if (testResult === 'PASSED') {
    return getBadgeUrl('tests', 'passed', 'brightgreen');
  } else if (testResult === 'FAILED') {
    return getBadgeUrl('tests', 'failed', 'red');
  } else {
    return getBadgeUrl('tests', 'skipped', 'lightgrey');
  }
}

function getBadgeUrl(subject, status, color) {
  return `https://img.shields.io/badge/${encodeURI(subject)}-${encodeURI(status)}-${color}.svg`;
}

function getConversionResultDescription(conversionResult) {
  if (conversionResult.passed) {
    return 'All files were successfully converted to JavaScript.';
  } else {
    return `
There were ${conversionResult.numErrors} errors out of
${conversionResult.numTotal} total files.

For more details on the errors, view the [error logs](./decaffeinate-errors.log)
`;
  }
}

function getTestResultDescription(testResult) {
  if (testResult === 'PASSED') {
    return 'All tests passed.';
  } else if (testResult === 'FAILED') {
    return 'Some tests failed.';
  } else {
    return 'Post-decaffeinate tests have not yet been set up for this project.';
  }
}
<commit_msg>Fix push failure due to shallow fetching (#71)<commit_after>import commander from 'commander';
import { exists, readdir, readFile, writeFile } from 'mz/fs';
import path from 'path';

import downloadFile from './downloadFile';
import run from './run';

export default function cli() {
  let project = null;
  commander
    .arguments('<project>')
    .description('Run decaffeinate on one of the sample projects.')
    .action(projectArg => project = projectArg)
    .option('--publish',
      `Push the resulting repository to the decaffeinate fork. The
           current git user must have permissions to do so.`)
    .parse(process.argv);

  runCli(project, commander.publish);
}

async function runCli(project, shouldPublish) {
  try {
    if (project === 'all') {
      await testAllProjects(shouldPublish);
    } else {
      await testProject(project, shouldPublish);
    }
  } catch (e) {
    process.exitCode = 1;
    console.error(`ERROR: ${e.message}`);
  }
}

async function testAllProjects(shouldPublish) {
  let projectNames = await readdir('./examples');
  console.log(`Processing all projects: ${projectNames.join(', ')}`);
  for (let project of projectNames) {
    console.log(`Processing project ${project}...`);
    await testProject(project, shouldPublish);
  }
  console.log(`Successfully processed all projects: ${projectNames.join(', ')}`);
}

async function testProject(project, shouldPublish) {
  let originalCwd = process.cwd();
  let exampleDir = path.resolve(`./examples/${project}`);
  if (!await exists(exampleDir)) {
    throw new Error(`Unknown project: ${project}`);
  }

  let config = require(`../examples/${project}/config`).default;

  let suffix = Math.floor(Math.random() * 1000000000000);
  let repoDir = `./tmp-projects/${project}-${suffix}`;
  await run(`mkdir ${repoDir}`);

  // As a special case, allow an example consisting of multiple project (like
  // all CoffeeScript projects in the atom org). In this case, we make a fresh
  // repo with the contents of other cloned repos.
  if (config.isMultiProject) {
    for (let {url, name} of config.cloneRepos) {
      await run(`git clone --depth=50 ${url} ${repoDir}/${name}`);
      await run(`rm -rf ${repoDir}/${name}/.git`);
    }
  } else {
    let cloneSuffix = config.branch ? `--branch ${config.branch}` : '';
    await run(`git clone --depth=50 ${config.cloneUrl} ${repoDir} ${cloneSuffix}`);
  }

  if (config.useDefaultConfig) {
    await run(`cp -R ./default-config/. ${repoDir}`);
  }
  if (await exists(`${exampleDir}/bulk-decaffeinate.config.js`)) {
    await run(`cp ${exampleDir}/bulk-decaffeinate.config.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/.eslintrc.js`)) {
    await run(`cp ${exampleDir}/.eslintrc.js ${repoDir}`);
  }
  if (await exists(`${exampleDir}/babelrc`)) {
    await run(`cp ${exampleDir}/babelrc ${repoDir}/.babelrc`);
  }
  if (await exists(`${exampleDir}/package.json`)) {
    await run(`cp ${exampleDir}/package.json ${repoDir}`);
  }

  process.chdir(repoDir);

  if (config.isMultiProject) {
    await run(`git init`);
    await run(`git add -A`);
    await run(`git commit --no-verify -m "Initial commit"`);
  }

  if (shouldPublish) {
    await run(`git remote add fork ${config.forkUrl}`);
    await run('git fetch --depth=50 fork');
    // If we're using a custom branch/ref, it may not be valid to push to it, so
    // skip this step. (Currently this fits all use cases, but it can be made
    // more flexible later if necessary.)
    if (!config.branch && !config.isMultiProject) {
      try {
        await run('git push fork');
      } catch (e) {
        await run('git fetch --unshallow');
        await run('git push fork');
      }
    }
  }

  if (await exists(`${exampleDir}/.gitignore_extension`)) {
    await run(`cat ${exampleDir}/.gitignore_extension >> .gitignore`);
  }

  await run('npm install');
  let dependencies = getDependencies(config);
  if (dependencies.length > 0) {
    await run(`npm install --save-dev --save-exact ${dependencies.join(' ')}`);
  }
  await run('git add -A');
  await run('git commit --no-verify -m "Add dependencies and config to prepare for decaffeinate"');

  if (config.beforeDecaffeinateScript) {
    await run(config.beforeDecaffeinateScript);
  }

  let conversionResult = await checkConversion(config);
  if (!conversionResult.passed) {
    await run('git add -A');
    await run('git commit --no-verify -m "Save decaffeinate error details"');

    await run('bulk-decaffeinate convert --skip-verify -p decaffeinate-successful-files.txt');
  } else {
    await run('bulk-decaffeinate convert --skip-verify');
  }

  await run('bulk-decaffeinate clean');
  // Make the patch its own commit after everything else so it's easier to
  // iterate on.
  if (await exists(`${exampleDir}/decaffeinate.patch`)) {
    await run(`git apply ${exampleDir}/decaffeinate.patch`);
    await run('git add -A');
    await run('git commit --no-verify -m "Modify the build to work with JavaScript"');
  }
  let testResult = await runTests(config);

  await downloadFile(getConversionResultBadgeUrl(conversionResult), './conversion-status.svg');
  await downloadFile(getTestResultBadgeUrl(testResult), './test-status.svg');
  await writeFile('./README.md', getReadme(project, conversionResult, testResult));
  await run('git add -A');
  await run('git commit --no-verify -m "Update README and badges with decaffeinate results"');

  if (shouldPublish) {
    await run('git push fork HEAD:decaffeinate -f');

    await run('git checkout --orphan gh-pages');
    await run('git rm --cached -r .');
    await run('git add conversion-status.svg');
    await run('git add test-status.svg');
    await run('git commit --no-verify -m "Add status SVGs to gh-pages branch"');
    await run('git push fork HEAD:gh-pages -f');
  }

  process.chdir(originalCwd);
}

const DEFAULT_PACKAGES = [
  'babel-cli',
  'babel-polyfill',
  'babel-preset-env',
  'babel-register',
  'eslint',
  'eslint-config-airbnb-base',
  'eslint-plugin-import',
];

function getDependencies(config) {
  let dependencies = [];
  if (config.useDefaultConfig) {
    dependencies.push(...DEFAULT_PACKAGES);
  }
  if (config.extraDependencies) {
    dependencies.push(...config.extraDependencies);
  }
  return dependencies;
}

async function checkConversion(config) {
  // To reduce build times, skip the check step if we expect success. If there
  // is a problem later, it will end up as a crash and the build will fail.
  if (config.expectConversionSuccess) {
    return {
      passed: true,
    };
  }
  await run('bulk-decaffeinate check');
  let hasErrorFile = await exists('./decaffeinate-errors.log');
  if (hasErrorFile) {
    let results = JSON.parse((await readFile('decaffeinate-results.json')).toString());
    let numErrors = results.filter(result => result.error).length;
    let numTotal = results.length;
    if (config.expectConversionSuccess) {
      process.exitCode = 1;
    }
    return {
      passed: false,
      numErrors,
      numTotal,
    };
  }
  return {
    passed: true,
  };
}

async function runTests(config) {
  if (config.skipTests) {
    console.log('Skipping tests for this project.');
    return 'SKIPPED';
  }
  try {
    if (config.testCommands) {
      for (let command of config.testCommands) {
        await run(command);
      }
    } else {
      await run('npm test');
    }
    return 'PASSED';
  } catch (e) {
    if (config.expectTestSuccess) {
      process.exitCode = 1;
    }
    return 'FAILED';
  }
}

function getReadme(project, conversionResult, testResult) {
  let jobId = process.env.TRAVIS_JOB_ID;
  let jobMessage = jobId ?
    `[Travis logs](https://travis-ci.org/decaffeinate/decaffeinate-example-builder/jobs/${jobId})` :
    '';
  return `\
# decaffeinate fork of ${project}

![Conversion Status](https://decaffeinate-examples.github.io/${project}/conversion-status.svg)
![Test Status](https://decaffeinate-examples.github.io/${project}/test-status.svg)

${jobMessage}

## Conversion results

${getConversionResultDescription(conversionResult)}

## Test results

${getTestResultDescription(testResult)}

## About this repository

This repository was generated automatically by the [decaffeinate-examples]
project using the [decaffeinate] tool.

[decaffeinate-examples]: https://github.com/decaffeinate/decaffeinate-examples
[decaffeinate]: https://github.com/decaffeinate/decaffeinate
`;
}

function getConversionResultBadgeUrl(conversionResult) {
  if (conversionResult.passed) {
    return getBadgeUrl('decaffeinate conversion', 'success', 'brightgreen');
  } else {
    return getBadgeUrl(
      'decaffeinate conversion',
      `${conversionResult.numErrors}/${conversionResult.numTotal} failed`,
      'red'
    );
  }
}

function getTestResultBadgeUrl(testResult) {
  if (testResult === 'PASSED') {
    return getBadgeUrl('tests', 'passed', 'brightgreen');
  } else if (testResult === 'FAILED') {
    return getBadgeUrl('tests', 'failed', 'red');
  } else {
    return getBadgeUrl('tests', 'skipped', 'lightgrey');
  }
}

function getBadgeUrl(subject, status, color) {
  return `https://img.shields.io/badge/${encodeURI(subject)}-${encodeURI(status)}-${color}.svg`;
}

function getConversionResultDescription(conversionResult) {
  if (conversionResult.passed) {
    return 'All files were successfully converted to JavaScript.';
  } else {
    return `
There were ${conversionResult.numErrors} errors out of
${conversionResult.numTotal} total files.

For more details on the errors, view the [error logs](./decaffeinate-errors.log)
`;
  }
}

function getTestResultDescription(testResult) {
  if (testResult === 'PASSED') {
    return 'All tests passed.';
  } else if (testResult === 'FAILED') {
    return 'Some tests failed.';
  } else {
    return 'Post-decaffeinate tests have not yet been set up for this project.';
  }
}
<|endoftext|>


<commit_before>var optimist = require('optimist'),
    chalk = require('chalk'),
    argv, url,
    ChanArchiver = require('./lib/chanarchive'),
    ChanTypes = require('./lib/chantypes');

var banner = [
'',
'              _                                         _      _               ',
'             | |                                       | |    (_)              ',
'        ____ | |__   _____  ____   _____   ____   ____ | |__   _  _   _  _____ ',
'       / ___)|  _ \\ (____ ||  _ \\ (____ | / ___) / ___)|  _ \\ | || | | || ___ |',
'      ( (___ | | | |/ ___ || | | |/ ___ || |    ( (___ | | | || | \\ V / | ____|',
'       \\____)|_| |_|\\_____||_| |_|\\_____||_|     \\____)|_| |_||_|  \\_/  |_____)',
'                                                                                ',
'                                                                Version : ' + chalk.cyan(require('./package').version),
''].join('\n');

console.log(banner);

argv = optimist
    .usage([
            '',
            chalk.green('Chan archiver'),
            '',
            'Run in the directory where you want the archive to be downloaded.',
            '',
            'Usage: chanarchive [OPTIONS] <URL>',
            '',
            'Current supported urls are',
            '',
            '4CHAN   :: http://boards.4chan.org/' + chalk.cyan('<BOARD>') + '/thread/' + chalk.cyan('<THREAD>'),
            '8CHAN   :: https://8chan.co/' + chalk.cyan('<BOARD>') + '/res/' + chalk.cyan('<THREAD>') + '.html',
            '420CHAN :: http://boards.420chan.org/' + chalk.cyan('<BOARD>') + '/res/' + chalk.cyan('<THREAD>') + '.php'
        ].join('\n'))
    .boolean('o')
    .alias('o', 'original-filenames')
        .describe('o', 'write original filenames instead of the timestamp filenames')
    .alias('w', 'watch')
        .describe('w', 'watch for new files.')
        .boolean('w')
    .alias('i', 'interval')
        .describe('i', 'watching interval in seconds.')
        .default('i', 10)
    .alias('v', 'version')
    .alias('t', 'threads')
        .describe('t', 'Num of concurrent downloads.')
        .default('t', 10)
    .describe('v', 'prints current version')
    .argv;

url = argv._[0];

if (argv.version) {
    console.error(require('./package').version);
    process.exit(0);
}

if (argv._.length !== 1 || url.indexOf('http') !== 0) {
    console.log(optimist.help());
    process.exit();
}

ChanTypes.get(url, function (type) {
    if (type) {
        chanArchiver = new ChanArchiver(type, url);
    } else {
        console.log(optimist.help());
        console.log(chalk.red('\n\nUnsupported url'));
        process.exit();
    }
});

process.on('SIGINT', function() {
    chanArchiver.stop();
    console.log('\nCTRL+C. Chan archiver exit.');
    return process.exit();
});

chanArchiver.useOriginalFileNames(argv.o);
chanArchiver.setMaxThreads(argv.threads);

if (argv.watch) {
    chanArchiver.setWatch(argv.interval * 1000);
}

chanArchiver.on('parse', function () {
    console.log(' ' + chalk.green(chanArchiver.queue.length) + ' new files to download');
});

chanArchiver.on('end', function () {
    console.log(' ' + chalk.green('Download finished.'));
});

chanArchiver.on('file:error', function (err, file) {
    console.log('file error');
    console.log(err);
});

chanArchiver.on('file:end', function (file) {
    if (file.existed) {
        console.log(' %s skipped, %s already exists', chalk.green(file.url), chalk.green(file.fileName));
    } else if (file.completed) {
        console.log(' %s saved as %s', chalk.green(file.url), chalk.green(file.fileName));
    }
});

chanArchiver.on('error', function (err) {
    console.log(' ' + chalk.red('Error: ' + err.message));
});

require('http').globalAgent.maxSockets =
require('https').globalAgent.maxSockets = Math.max(argv.threads, 10);

chanArchiver.download();
<commit_msg>Define chanArchiver variable, forgot about it<commit_after>var optimist = require('optimist'),
    chalk = require('chalk'),
    argv, url, chanArchiver,
    ChanArchiver = require('./lib/chanarchive'),
    ChanTypes = require('./lib/chantypes');

var banner = [
'',
'              _                                         _      _               ',
'             | |                                       | |    (_)              ',
'        ____ | |__   _____  ____   _____   ____   ____ | |__   _  _   _  _____ ',
'       / ___)|  _ \\ (____ ||  _ \\ (____ | / ___) / ___)|  _ \\ | || | | || ___ |',
'      ( (___ | | | |/ ___ || | | |/ ___ || |    ( (___ | | | || | \\ V / | ____|',
'       \\____)|_| |_|\\_____||_| |_|\\_____||_|     \\____)|_| |_||_|  \\_/  |_____)',
'                                                                                ',
'                                                                Version : ' + chalk.cyan(require('./package').version),
''].join('\n');

console.log(banner);

argv = optimist
    .usage([
            '',
            chalk.green('Chan archiver'),
            '',
            'Run in the directory where you want the archive to be downloaded.',
            '',
            'Usage: chanarchive [OPTIONS] <URL>',
            '',
            'Current supported urls are',
            '',
            '4CHAN   :: http://boards.4chan.org/' + chalk.cyan('<BOARD>') + '/thread/' + chalk.cyan('<THREAD>'),
            '8CHAN   :: https://8chan.co/' + chalk.cyan('<BOARD>') + '/res/' + chalk.cyan('<THREAD>') + '.html',
            '420CHAN :: http://boards.420chan.org/' + chalk.cyan('<BOARD>') + '/res/' + chalk.cyan('<THREAD>') + '.php'
        ].join('\n'))
    .boolean('o')
    .alias('o', 'original-filenames')
        .describe('o', 'write original filenames instead of the timestamp filenames')
    .alias('w', 'watch')
        .describe('w', 'watch for new files.')
        .boolean('w')
    .alias('i', 'interval')
        .describe('i', 'watching interval in seconds.')
        .default('i', 10)
    .alias('v', 'version')
    .alias('t', 'threads')
        .describe('t', 'Num of concurrent downloads.')
        .default('t', 10)
    .describe('v', 'prints current version')
    .argv;

url = argv._[0];

if (argv.version) {
    console.error(require('./package').version);
    process.exit(0);
}

if (argv._.length !== 1 || url.indexOf('http') !== 0) {
    console.log(optimist.help());
    process.exit(0);
}

ChanTypes.get(url, function (type) {
    if (type) {
        chanArchiver = new ChanArchiver(type, url);
    } else {
        console.log(optimist.help());
        console.log(chalk.red('\n\nUnsupported url'));
        process.exit();
    }
});

process.on('SIGINT', function() {
    chanArchiver.stop();
    console.log('\nCTRL+C. Chan archiver exit.');
    return process.exit();
});

chanArchiver.useOriginalFileNames(argv.o);
chanArchiver.setMaxThreads(argv.threads);

if (argv.watch) {
    chanArchiver.setWatch(argv.interval * 1000);
}

chanArchiver.on('parse', function () {
    console.log(' ' + chalk.green(chanArchiver.queue.length) + ' new files to download');
});

chanArchiver.on('end', function () {
    console.log(' ' + chalk.green('Download finished.'));
});

chanArchiver.on('file:error', function (err, file) {
    console.log('file error');
    console.log(err);
});

chanArchiver.on('file:end', function (file) {
    if (file.existed) {
        console.log(' %s skipped, %s already exists', chalk.green(file.url), chalk.green(file.fileName));
    } else if (file.completed) {
        console.log(' %s saved as %s', chalk.green(file.url), chalk.green(file.fileName));
    }
});

chanArchiver.on('error', function (err) {
    console.log(' ' + chalk.red('Error: ' + err.message));
});

require('http').globalAgent.maxSockets =
require('https').globalAgent.maxSockets = Math.max(argv.threads, 10);

chanArchiver.download();
<|endoftext|>


<commit_before>(function() {
    'use strict';

    var DIR     = './',
        config  = require(DIR + 'config'),
        mellow  = require('mellow');

    module.exports = function(dir) {
        var root = config('root') || '/';

        dir = mellow.pathToWin(dir, root);

        return dir;
    };
})();
<commit_msg>chore(root) rm iife<commit_after>'use strict';

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

module.exports = function(dir) {
    var root = config('root') || '/';

    return mellow.pathToWin(dir, root);
};

<|endoftext|>


<commit_before>'use strict';

const BaseEntity = require('./baseentity.js');

/**
 * Represents an in-game player.
 */
class Player extends BaseEntity {
  constructor(demo, index, classId, serialNum, baseline) {
    super(demo, index, classId, serialNum, baseline);

    /**
     * The 'client slot' is the index into various arrays such as the userinfo table.
     */
    this.clientSlot = index - 1;
  }

  /**
   * @returns {int} Current health
   */
  get health() {
    return this.getProp('DT_BasePlayer', 'm_iHealth');
  }

  get eyeAngles() {
    return {
      pitch: this.getProp('DT_CSPlayer', 'm_angEyeAngles[0]'),
      yaw: this.getProp('DT_CSPlayer', 'm_angEyeAngles[1]')
    };
  }

  get position() {
    let xy = this.getProp('DT_CSLocalPlayerExclusive', 'm_vecOrigin');
    return {
      x: xy.x,
      y: xy.y,
      z: this.getProp('DT_CSLocalPlayerExclusive', 'm_vecOrigin[2]')
    };
  }

  /**
   * @returns {int} Current cash
   */
  get account() {
    return this.getProp('DT_CSPlayer', 'm_iAccount');
  }

  /**
   * @returns {int} 0: Alive, 1: Dying, 2: Dead
   */
  get lifeState() {
    return this.getProp('DT_BasePlayer', 'm_lifeState');
  }

  /**
   * @returns {bool} lifeState == 0
   */
  get isAlive() {
    return this.lifeState === 0;
  }

  /**
   * @returns {PlayerInfo|null} User info associated with this player
   */
  get userInfo() {
    let userInfoTable = this._demo.stringTables.findTableByName('userinfo');
    return userInfoTable.entries[this.clientSlot].userData;
  }

  /**
   * @returns {int} User ID
   */
  get userId() {
    return this.userInfo.userId;
  }

  /**
   * @returns {string} Steam ID
   */
  get steamId() {
    return this.userInfo.guid;
  }

  /**
   * @returns {string} Player name
   */
  get name() {
    return this.userInfo.name;
  }

  /**
   * @returns {bool} Is this player fake (i.e. a bot)
   */
  get isFakePlayer() {
    return this.userInfo.fakePlayer;
  }

  /**
   * @returns {bool} Is this player a HLTV relay
   */
  get isHltv() {
    return this.userInfo.isHltv;
  }

  /**
   * @returns {int} Player armor (0-100)
   */
  get armor() {
    return this.getProp('DT_CSPlayer', 'm_ArmorValue');
  }

  /**
   * @returns {string} Current navmesh place name
   */
  get placeName() {
    return this.getProp('DT_BasePlayer', 'm_szLastPlaceName');
  }

  /**
   * @returns {Entity|null} Currently held weapon
   */
  get weapon() {
    return this._demo.entities.getByHandle(this.getProp('DT_BaseCombatCharacter', 'm_hActiveWeapon'));
  }

  /**
   * @returns {Entity[]} All weapons helds by this player
   */
  get weapons() {
    let weapons = [];

    for(let index in this.props['m_hMyWeapons']) {
      let weapon = this._demo.entities.getByHandle(this.props['m_hMyWeapons'][index]);

      if (weapon) {
        weapons.push(weapon);
      }
    }

    return weapons;
  }

  /**
   * @returns {bool} Is the player is the bomb zone?
   */
  get isInBombZone() {
    return this.getProp('DT_CSPlayer', 'm_bInBombZone');
  }

  /**
   * @returns {bool} Is the player in the buy zone?
   */
  get isInBuyZone() {
    return this.getProp('DT_CSPlayer', 'm_bInBuyZone');
  }

  /**
   * @returns {bool} Is the player defusing?
   */
  get isDefusing() {
    return this.getProp('DT_CSPlayer', 'm_bIsDefusing');
  }

  /**
   * @returns {bool} Does the player have a defuser?
   */
  get hasDefuser() {
    return this.getProp('DT_CSPlayer', 'm_bHasDefuser');
  }

  /**
   * @returns {bool} Does the player have a helmet?
   */
  get hasHelmet() {
    return this.getProp('DT_CSPlayer', 'm_bHasHelmet');
  }

  /**
   * @returns {int} How many kills the player has made
   */
  get kills() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let kills = pr.props['m_iKills'];
    return kills[Object.keys(kills)[this.index]];
  }

  /**
   * @returns {int} How many assists the player has made
   */
  get assists() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let assists = pr.props['m_iAssists'];
    return assists[Object.keys(assists)[this.index]];
  }

  /**
   * @returns {int} How many times the player has died
   */
  get deaths() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let deaths = pr.props['m_iDeaths'];
    return deaths[Object.keys(deaths)[this.index]];
  }

  /**
   * @returns {bool} Whether the player holds the C4
   */
  get hasC4() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    return pr.getProp('DT_CSPlayerResource', 'm_iPlayerC4') === this.index;
  }

  /**
   * @returns {bool} Has this player been spotted by any others?
   */
  get isSpotted() {
    return this.getProp('DT_BaseEntity', 'm_bSpotted');
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Is this player spotted by the other?
   */
  isSpottedBy(other) {
    let bit = other.clientSlot;
    let mask = null;

    if (other.clientSlot < 32) {
      mask = this.getProp('m_bSpottedByMask', '000');
    } else {
      bit = other.clientSlot - 32;
      mask = this.getProp('m_bSpottedByMask', '001');
    }

    return (mask & (1 << bit)) !== 0;
  }

  /**
   * @returns {Player[]} Players that have spotted this player
   */
  get allSpotters() {
    let masks = [
      this.getProp('m_bSpottedByMask', '000'),
      this.getProp('m_bSpottedByMask', '001')
    ];

    return Array.from({length: 64}, (_, i) => i)
      .filter(i => {
        let bit = i % 32;
        let mask = masks[(i/32) >> 0];
        return (mask & (1 << bit)) !== 0;
      })
      .map(clientSlot => this._demo.entities.entities[clientSlot + 1]);
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Has this player spotted the other?
   */
  hasSpotted(other) {
    return other.isSpottedBy(this);
  }

  /**
   * @returns {Player[]} All players that this player has spotted
   */
  get allSpotted() {
    return this._demo.players
      .filter(p => p.clientSlot !== this.clientSlot && this.hasSpotted(p));
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Whether the two players are on the same team
   */
  isFriendly(other) {
    let sameTeam = this.teamNumber === other.teamNumber;
    let teammatesAreEnemies = this._demo.conVars.vars['mp_teammates_are_enemies'] || 0;

    return sameTeam && !teammatesAreEnemies;
  }
}

module.exports = Player;
<commit_msg>Added Player.steam64Id<commit_after>'use strict';

const BaseEntity = require('./baseentity.js');

/**
 * Represents an in-game player.
 */
class Player extends BaseEntity {
  constructor(demo, index, classId, serialNum, baseline) {
    super(demo, index, classId, serialNum, baseline);

    /**
     * The 'client slot' is the index into various arrays such as the userinfo table.
     */
    this.clientSlot = index - 1;
  }

  /**
   * @returns {int} Current health
   */
  get health() {
    return this.getProp('DT_BasePlayer', 'm_iHealth');
  }

  get eyeAngles() {
    return {
      pitch: this.getProp('DT_CSPlayer', 'm_angEyeAngles[0]'),
      yaw: this.getProp('DT_CSPlayer', 'm_angEyeAngles[1]')
    };
  }

  get position() {
    let xy = this.getProp('DT_CSLocalPlayerExclusive', 'm_vecOrigin');
    return {
      x: xy.x,
      y: xy.y,
      z: this.getProp('DT_CSLocalPlayerExclusive', 'm_vecOrigin[2]')
    };
  }

  /**
   * @returns {int} Current cash
   */
  get account() {
    return this.getProp('DT_CSPlayer', 'm_iAccount');
  }

  /**
   * @returns {int} 0: Alive, 1: Dying, 2: Dead
   */
  get lifeState() {
    return this.getProp('DT_BasePlayer', 'm_lifeState');
  }

  /**
   * @returns {bool} lifeState == 0
   */
  get isAlive() {
    return this.lifeState === 0;
  }

  /**
   * @returns {PlayerInfo|null} User info associated with this player
   */
  get userInfo() {
    let userInfoTable = this._demo.stringTables.findTableByName('userinfo');
    return userInfoTable.entries[this.clientSlot].userData;
  }

  /**
   * @returns {int} User ID
   */
  get userId() {
    return this.userInfo.userId;
  }

  /**
   * @returns {string} Steam ID
   */
  get steamId() {
    return this.userInfo.guid;
  }

  /**
   * @returns {string} Steam 64 ID
   */
  get steam64Id() {
    return this.userInfo.xuid.toString();
  }

  /**
   * @returns {string} Player name
   */
  get name() {
    return this.userInfo.name;
  }

  /**
   * @returns {bool} Is this player fake (i.e. a bot)
   */
  get isFakePlayer() {
    return this.userInfo.fakePlayer;
  }

  /**
   * @returns {bool} Is this player a HLTV relay
   */
  get isHltv() {
    return this.userInfo.isHltv;
  }

  /**
   * @returns {int} Player armor (0-100)
   */
  get armor() {
    return this.getProp('DT_CSPlayer', 'm_ArmorValue');
  }

  /**
   * @returns {string} Current navmesh place name
   */
  get placeName() {
    return this.getProp('DT_BasePlayer', 'm_szLastPlaceName');
  }

  /**
   * @returns {Entity|null} Currently held weapon
   */
  get weapon() {
    return this._demo.entities.getByHandle(this.getProp('DT_BaseCombatCharacter', 'm_hActiveWeapon'));
  }

  /**
   * @returns {Entity[]} All weapons helds by this player
   */
  get weapons() {
    let weapons = [];

    for(let index in this.props['m_hMyWeapons']) {
      let weapon = this._demo.entities.getByHandle(this.props['m_hMyWeapons'][index]);

      if (weapon) {
        weapons.push(weapon);
      }
    }

    return weapons;
  }

  /**
   * @returns {bool} Is the player is the bomb zone?
   */
  get isInBombZone() {
    return this.getProp('DT_CSPlayer', 'm_bInBombZone');
  }

  /**
   * @returns {bool} Is the player in the buy zone?
   */
  get isInBuyZone() {
    return this.getProp('DT_CSPlayer', 'm_bInBuyZone');
  }

  /**
   * @returns {bool} Is the player defusing?
   */
  get isDefusing() {
    return this.getProp('DT_CSPlayer', 'm_bIsDefusing');
  }

  /**
   * @returns {bool} Does the player have a defuser?
   */
  get hasDefuser() {
    return this.getProp('DT_CSPlayer', 'm_bHasDefuser');
  }

  /**
   * @returns {bool} Does the player have a helmet?
   */
  get hasHelmet() {
    return this.getProp('DT_CSPlayer', 'm_bHasHelmet');
  }

  /**
   * @returns {int} How many kills the player has made
   */
  get kills() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let kills = pr.props['m_iKills'];
    return kills[Object.keys(kills)[this.index]];
  }

  /**
   * @returns {int} How many assists the player has made
   */
  get assists() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let assists = pr.props['m_iAssists'];
    return assists[Object.keys(assists)[this.index]];
  }

  /**
   * @returns {int} How many times the player has died
   */
  get deaths() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    let deaths = pr.props['m_iDeaths'];
    return deaths[Object.keys(deaths)[this.index]];
  }

  /**
   * @returns {bool} Whether the player holds the C4
   */
  get hasC4() {
    let pr = this._demo.entities.getSingleton('DT_CSPlayerResource');
    return pr.getProp('DT_CSPlayerResource', 'm_iPlayerC4') === this.index;
  }

  /**
   * @returns {bool} Has this player been spotted by any others?
   */
  get isSpotted() {
    return this.getProp('DT_BaseEntity', 'm_bSpotted');
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Is this player spotted by the other?
   */
  isSpottedBy(other) {
    let bit = other.clientSlot;
    let mask = null;

    if (other.clientSlot < 32) {
      mask = this.getProp('m_bSpottedByMask', '000');
    } else {
      bit = other.clientSlot - 32;
      mask = this.getProp('m_bSpottedByMask', '001');
    }

    return (mask & (1 << bit)) !== 0;
  }

  /**
   * @returns {Player[]} Players that have spotted this player
   */
  get allSpotters() {
    let masks = [
      this.getProp('m_bSpottedByMask', '000'),
      this.getProp('m_bSpottedByMask', '001')
    ];

    return Array.from({length: 64}, (_, i) => i)
      .filter(i => {
        let bit = i % 32;
        let mask = masks[(i/32) >> 0];
        return (mask & (1 << bit)) !== 0;
      })
      .map(clientSlot => this._demo.entities.entities[clientSlot + 1]);
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Has this player spotted the other?
   */
  hasSpotted(other) {
    return other.isSpottedBy(this);
  }

  /**
   * @returns {Player[]} All players that this player has spotted
   */
  get allSpotted() {
    return this._demo.players
      .filter(p => p.clientSlot !== this.clientSlot && this.hasSpotted(p));
  }

  /**
   * @param {Player} other - Other player entity
   * @returns {bool} Whether the two players are on the same team
   */
  isFriendly(other) {
    let sameTeam = this.teamNumber === other.teamNumber;
    let teammatesAreEnemies = this._demo.conVars.vars['mp_teammates_are_enemies'] || 0;

    return sameTeam && !teammatesAreEnemies;
  }
}

module.exports = Player;
<|endoftext|>


<commit_before>import { GraphQLBoolean, GraphQLList, GraphQLString } from 'graphql';
import client from 'util/client';

import {
  createFilterType,
  createSortType,
  createConnectionType,
  getSortArgs,
  pagingArgs,
  timeRangeInput,
  moreLikeThisInput,
  getRangeFieldParamFromArithmeticExpression,
} from 'graphql/util';
import scrapUrls from 'util/scrapUrls';

import Reply from 'graphql/models/Reply';
import ReplyTypeEnum from 'graphql/models/ReplyTypeEnum';

export default {
  args: {
    filter: {
      type: createFilterType('ListReplyFilter', {
        userId: {
          type: GraphQLString,
        },
        appId: {
          type: GraphQLString,
        },
        moreLikeThis: {
          type: moreLikeThisInput,
        },
        selfOnly: {
          type: GraphQLBoolean,
          description: 'List the replies created by the requester themselves',
        },
        type: {
          type: ReplyTypeEnum,
          // FIXME: No deprecationReason for input object types yet
          // https://github.com/graphql/graphql-spec/pull/525
          description: '[Deprecated] use types instead.',
        },
        types: {
          type: new GraphQLList(ReplyTypeEnum),
          description: 'List the replies of certain types',
        },
        createdAt: {
          type: timeRangeInput,
          description:
            'List only the replies that were created between the specific time range.',
        },
      }),
    },
    orderBy: {
      type: createSortType('ListReplyOrderBy', ['_score', 'createdAt']),
    },
    ...pagingArgs,
  },
  async resolve(
    rootValue,
    { filter = {}, orderBy = [], ...otherParams },
    { userId, appId, loaders }
  ) {
    const body = {
      sort: getSortArgs(orderBy),
      track_scores: true, // for _score sorting
    };

    // Collecting queries that will be used in bool queries later
    const shouldQueries = []; // Affects scores
    const filterQueries = []; // Not affects scores

    if (filter.moreLikeThis) {
      const scrapResults = (await scrapUrls(filter.moreLikeThis.like, {
        client,
        cacheLoader: loaders.urlLoader,
      })).filter(r => r);

      const likeQuery = [
        filter.moreLikeThis.like,
        ...scrapResults.map(({ title, summary }) => `${title} ${summary}`),
      ];

      shouldQueries.push(
        {
          more_like_this: {
            fields: ['text', 'reference'],
            like: likeQuery,
            min_term_freq: 1,
            min_doc_freq: 1,
            minimum_should_match:
              filter.moreLikeThis.minimumShouldMatch || '10<70%',
          },
        },
        {
          nested: {
            path: 'hyperlinks',
            score_mode: 'sum',
            query: {
              more_like_this: {
                fields: ['hyperlinks.title', 'hyperlinks.summary'],
                like: likeQuery,
                min_term_freq: 1,
                min_doc_freq: 1,
                minimum_should_match:
                  filter.moreLikeThis.minimumShouldMatch || '10<70%',
              },
            },
            inner_hits: {
              highlight: {
                order: 'score',
                fields: {
                  'hyperlinks.title': {
                    number_of_fragments: 1, // Return only 1 piece highlight text
                    fragment_size: 200, // word count of highlighted fragment
                    type: 'plain',
                  },
                  'hyperlinks.summary': {
                    number_of_fragments: 1, // Return only 1 piece highlight text
                    fragment_size: 200, // word count of highlighted fragment
                    type: 'plain',
                  },
                },
                require_field_match: false,
                pre_tags: ['<HIGHLIGHT>'],
                post_tags: ['</HIGHLIGHT>'],
              },
            },
          },
        }
      );

      // Additionally, match the scrapped URLs with other reply's scrapped urls
      //
      const urls = scrapResults.reduce((urls, result) => {
        if (!result) return urls;

        if (result.url) urls.push(result.url);
        if (result.canonical) urls.push(result.canonical);
        return urls;
      }, []);

      if (urls.length > 0) {
        shouldQueries.push({
          nested: {
            path: 'hyperlinks',
            score_mode: 'sum',
            query: {
              terms: {
                'hyperlinks.url': urls,
              },
            },
          },
        });
      }
    }

    ['userId', 'appId', 'type' /* deprecated */].forEach(field => {
      if (!filter[field]) return;
      filterQueries.push({ term: { [field]: filter[field] } });
    });

    if (filter.types && filter.types.length > 0) {
      filterQueries.push({
        terms: {
          type: filter.types,
        },
      });
    }

    if (filter.selfOnly) {
      if (!userId) throw new Error('selfOnly can be set only after log in');
      filterQueries.push({ term: { userId } }, { term: { appId } });
    }

    if (filter.createdAt) {
      filterQueries.push({
        range: {
          createdAt: getRangeFieldParamFromArithmeticExpression(
            filter.createdAt
          ),
        },
      });
    }

    body.query = {
      bool: {
        should:
          shouldQueries.length === 0 ? [{ match_all: {} }] : shouldQueries,
        filter: filterQueries,
        minimum_should_match: 1, // At least 1 "should" query should present
      },
    };

    // should return search context for resolveEdges & resolvePageInfo
    return {
      index: 'replies',
      type: 'doc',
      body,
      ...otherParams,
    };
  },
  type: createConnectionType('ListReplyConnection', Reply),
};
<commit_msg>Fix Reply reference search, may be a bug form elasticsearch<commit_after>import { GraphQLBoolean, GraphQLList, GraphQLString } from 'graphql';
import client from 'util/client';

import {
  createFilterType,
  createSortType,
  createConnectionType,
  getSortArgs,
  pagingArgs,
  timeRangeInput,
  moreLikeThisInput,
  getRangeFieldParamFromArithmeticExpression,
} from 'graphql/util';
import scrapUrls from 'util/scrapUrls';

import Reply from 'graphql/models/Reply';
import ReplyTypeEnum from 'graphql/models/ReplyTypeEnum';

export default {
  args: {
    filter: {
      type: createFilterType('ListReplyFilter', {
        userId: {
          type: GraphQLString,
        },
        appId: {
          type: GraphQLString,
        },
        moreLikeThis: {
          type: moreLikeThisInput,
        },
        selfOnly: {
          type: GraphQLBoolean,
          description: 'List the replies created by the requester themselves',
        },
        type: {
          type: ReplyTypeEnum,
          // FIXME: No deprecationReason for input object types yet
          // https://github.com/graphql/graphql-spec/pull/525
          description: '[Deprecated] use types instead.',
        },
        types: {
          type: new GraphQLList(ReplyTypeEnum),
          description: 'List the replies of certain types',
        },
        createdAt: {
          type: timeRangeInput,
          description:
            'List only the replies that were created between the specific time range.',
        },
      }),
    },
    orderBy: {
      type: createSortType('ListReplyOrderBy', ['_score', 'createdAt']),
    },
    ...pagingArgs,
  },
  async resolve(
    rootValue,
    { filter = {}, orderBy = [], ...otherParams },
    { userId, appId, loaders }
  ) {
    const body = {
      sort: getSortArgs(orderBy),
      track_scores: true, // for _score sorting
    };

    // Collecting queries that will be used in bool queries later
    const shouldQueries = []; // Affects scores
    const filterQueries = []; // Not affects scores

    if (filter.moreLikeThis) {
      const scrapResults = (await scrapUrls(filter.moreLikeThis.like, {
        client,
        cacheLoader: loaders.urlLoader,
      })).filter(r => r);

      const likeQuery = [
        filter.moreLikeThis.like,
        ...scrapResults.map(({ title, summary }) => `${title} ${summary}`),
      ];

      shouldQueries.push(
        {
          more_like_this: {
            fields: ['text'],
            like: likeQuery,
            min_term_freq: 1,
            min_doc_freq: 1,
            minimum_should_match:
              filter.moreLikeThis.minimumShouldMatch || '10<70%',
          },
        },
        {
          more_like_this: {
            fields: ['reference'],
            like: likeQuery,
            min_term_freq: 1,
            min_doc_freq: 1,
            minimum_should_match:
              filter.moreLikeThis.minimumShouldMatch || '10<70%',
          },
        },
        {
          nested: {
            path: 'hyperlinks',
            score_mode: 'sum',
            query: {
              more_like_this: {
                fields: ['hyperlinks.title', 'hyperlinks.summary'],
                like: likeQuery,
                min_term_freq: 1,
                min_doc_freq: 1,
                minimum_should_match:
                  filter.moreLikeThis.minimumShouldMatch || '10<70%',
              },
            },
            inner_hits: {
              highlight: {
                order: 'score',
                fields: {
                  'hyperlinks.title': {
                    number_of_fragments: 1, // Return only 1 piece highlight text
                    fragment_size: 200, // word count of highlighted fragment
                    type: 'plain',
                  },
                  'hyperlinks.summary': {
                    number_of_fragments: 1, // Return only 1 piece highlight text
                    fragment_size: 200, // word count of highlighted fragment
                    type: 'plain',
                  },
                },
                require_field_match: false,
                pre_tags: ['<HIGHLIGHT>'],
                post_tags: ['</HIGHLIGHT>'],
              },
            },
          },
        }
      );

      // Additionally, match the scrapped URLs with other reply's scrapped urls
      //
      const urls = scrapResults.reduce((urls, result) => {
        if (!result) return urls;

        if (result.url) urls.push(result.url);
        if (result.canonical) urls.push(result.canonical);
        return urls;
      }, []);

      if (urls.length > 0) {
        shouldQueries.push({
          nested: {
            path: 'hyperlinks',
            score_mode: 'sum',
            query: {
              terms: {
                'hyperlinks.url': urls,
              },
            },
          },
        });
      }
    }

    ['userId', 'appId', 'type' /* deprecated */].forEach(field => {
      if (!filter[field]) return;
      filterQueries.push({ term: { [field]: filter[field] } });
    });

    if (filter.types && filter.types.length > 0) {
      filterQueries.push({
        terms: {
          type: filter.types,
        },
      });
    }

    if (filter.selfOnly) {
      if (!userId) throw new Error('selfOnly can be set only after log in');
      filterQueries.push({ term: { userId } }, { term: { appId } });
    }

    if (filter.createdAt) {
      filterQueries.push({
        range: {
          createdAt: getRangeFieldParamFromArithmeticExpression(
            filter.createdAt
          ),
        },
      });
    }

    body.query = {
      bool: {
        should:
          shouldQueries.length === 0 ? [{ match_all: {} }] : shouldQueries,
        filter: filterQueries,
        minimum_should_match: 1, // At least 1 "should" query should present
      },
    };

    // should return search context for resolveEdges & resolvePageInfo
    return {
      index: 'replies',
      type: 'doc',
      body,
      ...otherParams,
    };
  },
  type: createConnectionType('ListReplyConnection', Reply),
};
<|endoftext|>


<commit_before>var Feeds = require('./client/feeds'),
    Data = require('./client/data'),
    Groups = require('./client/groups');

var proto = Client.prototype;

function Client(username, key) {

  if (!(this instanceof Client)) {
    return new Client(username, key);
  }

  if(!username) {
    throw 'You must provide an Adafruit IO username';
  }

  if(!key) {
    throw 'You must provide an Adafruit IO API key';
  }

  this.username = username;
  this.key = key;

}

proto.username = false;
proto.key = false;

proto.feeds = function(id, cb) {

  var feeds;

  if(typeof id != 'function') {
    feeds = new Feeds(this.username, this.key, id);
  } else {
    feeds = new Feeds(this.username, this.key);
    cb = id;
  }

  if(typeof cb == 'function') {
    return feeds.load(cb);
  }

  return feeds;

};

proto.create_feed = function(data, cb) {

  var feeds = new Feeds(this.username, this.key);

  return feeds.create(data, cb);

};

proto.groups = function(id, cb) {

  var groups;

  if(typeof id != 'function') {
    groups = new Groups(this.key, id);
  } else {
    groups = new Groups(this.key);
    cb = id;
  }

  if(typeof cb == 'function') {
    return groups.load(cb);
  }

  return groups;

};

proto.create_group = function(data, cb) {

  var groups = new Groups(this.key);

  return groups.create(data, cb);

};

proto.send = function(feed_name, data, cb) {

  var data = new Data(this.key, feed_name);

  return data.send(data, cb);

};

exports = module.exports = Client;
<commit_msg>Fix send method<commit_after>var Feeds = require('./client/feeds'),
    Data = require('./client/data'),
    Groups = require('./client/groups');

var proto = Client.prototype;

function Client(username, key) {

  if (!(this instanceof Client)) {
    return new Client(username, key);
  }

  if(!username) {
    throw 'You must provide an Adafruit IO username';
  }

  if(!key) {
    throw 'You must provide an Adafruit IO API key';
  }

  this.username = username;
  this.key = key;

}

proto.username = false;
proto.key = false;

proto.feeds = function(id, cb) {

  var feeds;

  if(typeof id != 'function') {
    feeds = new Feeds(this.username, this.key, id);
  } else {
    feeds = new Feeds(this.username, this.key);
    cb = id;
  }

  if(typeof cb == 'function') {
    return feeds.load(cb);
  }

  return feeds;

};

proto.create_feed = function(data, cb) {

  var feeds = new Feeds(this.username, this.key);

  return feeds.create(data, cb);

};

proto.groups = function(id, cb) {

  var groups;

  if(typeof id != 'function') {
    groups = new Groups(this.key, id);
  } else {
    groups = new Groups(this.key);
    cb = id;
  }

  if(typeof cb == 'function') {
    return groups.load(cb);
  }

  return groups;

};

proto.create_group = function(data, cb) {

  var groups = new Groups(this.key);

  return groups.create(data, cb);

};

proto.send = function(feed_name, data, cb) {

  var feed_data = new Data(this.key, feed_name);

  return feed_data.send(data, cb);

};

exports = module.exports = Client;
<|endoftext|>


<commit_before>/*
 *  danmaku.js
 *  2015/10/11
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.namespace(function() {

pbr.danmaku = pbr.danmaku || {};

var action = bulletml.dsl.action;
var actionRef = bulletml.dsl.actionRef;
var bullet = bulletml.dsl.bullet;
var bulletRef = bulletml.dsl.bulletRef;
var fire = bulletml.dsl.fire;
var fireRef = bulletml.dsl.fireRef;
var changeDirection = bulletml.dsl.changeDirection;
var changeSpeed = bulletml.dsl.changeSpeed;
var accel = bulletml.dsl.accel;
var wait = bulletml.dsl.wait;
var vanish = bulletml.dsl.vanish;
var repeat = bulletml.dsl.repeat;
var bindVar = bulletml.dsl.bindVar;
var notify = bulletml.dsl.notify;
var direction = bulletml.dsl.direction;
var speed = bulletml.dsl.speed;
var horizontal = bulletml.dsl.horizontal;
var vertical = bulletml.dsl.vertical;
var fireOption = bulletml.dsl.fireOption;
var offsetX = bulletml.dsl.offsetX;
var offsetY = bulletml.dsl.offsetY;
var autonomy = bulletml.dsl.autonomy;

var interval = function(v) {
  return wait("{0} * (0.3 + (1.0 - $densityRank) * 0.7)".format(v));
};
var spd = function(v) {
  return speed("{0} * (1.0 + $speedRank * 2.0)".format(v));
};
var spdSeq = function(v) {
  return speed("{0} * (1.0 + $speedRank * 2.0)".format(v), "sequence");
};

var R0 = bullet({
  type: 4
});
var R1 = bullet({
  type: 5
});
var R2 = bullet({
  type: 6
});
var R3 = bullet({
  type: 7
});
var B4 = bullet({
  type: 8
});
var B5 = bullet({
  type: 9
});
var R4 = bullet({
  type: 10
});
var R5 = bullet({
  type: 11
});
var DM = bullet({
  dummy: true
});

// URwp
var basic = function(s, dir) {
  return new bulletml.Root({
    top: action([
      interval(10),
      repeat(Infinity, [
        fire(DM, spd(s), direction(dir)),
        repeat("$burst + 1", [
          fire(R2, spdSeq(0.15), direction(0, "sequence")),
        ]),
        interval(50),
      ]),
    ]),
  });
};
pbr.danmaku.basic = basic(1, 0);
pbr.danmaku.basicR1 = basic(1, -5);
pbr.danmaku.basicL1 = basic(1, +5);
pbr.danmaku.basicR2 = basic(1, -15);
pbr.danmaku.basicL2 = basic(1, +15);
pbr.danmaku.basicF = basic(1.2, 0);
pbr.danmaku.basicFR1 = basic(1.2, -5);
pbr.danmaku.basicFL1 = basic(1.2, +5);
pbr.danmaku.basicFR2 = basic(1.2, -15);
pbr.danmaku.basicFL2 = basic(1.2, +15);

// URw3way
var basic3way = function(dir) {
  return new bulletml.Root({
    top: action([
      interval(10),
      repeat(Infinity, [
        fire(DM, spd(1), direction(dir - 7)),
        repeat("$burst + 1", [
          fire(R2, spdSeq(0), direction(0, "sequence")),
          fire(R2, spdSeq(0), direction(7, "sequence")),
          fire(R2, spdSeq(0), direction(7, "sequence")),
          fire(DM, spdSeq(0.05), direction(-14, "sequence")),
        ]),
        interval(50),
      ]),
    ]),
  });
};
pbr.danmaku.basic3way = basic3way(0);
pbr.danmaku.basic3wayR1 = basic3way(-5);
pbr.danmaku.basic3wayL1 = basic3way(+5);
pbr.danmaku.basic3wayR2 = basic3way(-15);
pbr.danmaku.basic3wayL2 = basic3way(+15);

// URԗp
var forward = function(s, dir) {
  return new bulletml.Root({
    top: action([
      interval(10),
      repeat(Infinity, [
        repeat(3, [
          fire(DM, spd(s), direction(dir, "relative")),
          repeat("$burst + 1", [
            fire(R2, spdSeq(0.15), direction(0, "sequence")),
          ]),
          interval(10),
        ]),
        interval(50),
      ]),
    ]),
  });
};
pbr.danmaku.forward = forward(1, 0);
pbr.danmaku.forwardR1 = forward(1, -5);
pbr.danmaku.forwardL1 = forward(1, +5);
pbr.danmaku.forwardR2 = forward(1, -15);
pbr.danmaku.forwardL2 = forward(1, +15);
pbr.danmaku.forwardF = forward(1.2, 0);
pbr.danmaku.forwardFR1 = forward(1.2, -5);
pbr.danmaku.forwardFL1 = forward(1.2, +5);
pbr.danmaku.forwardFR2 = forward(1.2, -15);
pbr.danmaku.forwardFL2 = forward(1.2, +15);

// UR3way
var forward3way = function(s, dir) {
  return new bulletml.Root({
    top: action([
      interval(10),
      repeat(Infinity, [
        repeat(3, [
          fire(DM, spd(s), direction(dir + "-5", "relative")),
          repeat("$burst + 1", [
            fire(R2, spdSeq(0), direction(+5, "sequence")),
            fire(R2, spdSeq(0), direction(+5, "sequence")),
            fire(R2, spdSeq(0), direction(+5, "sequence")),
            fire(DM, spdSeq(0.15), direction(-15, "sequence")),
          ]),
          interval(10),
        ]),
        interval(50),
      ]),
    ]),
  });
};
pbr.danmaku.forward3way = forward3way(1, 0);
pbr.danmaku.forward3wayR1 = forward3way(1, -5);
pbr.danmaku.forward3wayL1 = forward3way(1, +5);
pbr.danmaku.forward3wayR2 = forward3way(1, -15);
pbr.danmaku.forward3wayL2 = forward3way(1, +15);
pbr.danmaku.forward3wayF = forward3way(1.2, 0);
pbr.danmaku.forward3wayFR1 = forward3way(1.2, -5);
pbr.danmaku.forward3wayFL1 = forward3way(1.2, +5);
pbr.danmaku.forward3wayFR2 = forward3way(1.2, -15);
pbr.danmaku.forward3wayFL2 = forward3way(1.2, +15);

});

<commit_msg>update danmaku<commit_after>/*
 *  danmaku.js
 *  2015/10/11
 *  @auther minimo
 *  This Program is MIT license.
 */

phina.namespace(function() {

pbr.danmaku = pbr.danmaku || {};

var action = bulletml.dsl.action;
var actionRef = bulletml.dsl.actionRef;
var bullet = bulletml.dsl.bullet;
var bulletRef = bulletml.dsl.bulletRef;
var fire = bulletml.dsl.fire;
var fireRef = bulletml.dsl.fireRef;
var changeDirection = bulletml.dsl.changeDirection;
var changeSpeed = bulletml.dsl.changeSpeed;
var accel = bulletml.dsl.accel;
var wait = bulletml.dsl.wait;
var vanish = bulletml.dsl.vanish;
var repeat = bulletml.dsl.repeat;
var bindVar = bulletml.dsl.bindVar;
var notify = bulletml.dsl.notify;
var direction = bulletml.dsl.direction;
var speed = bulletml.dsl.speed;
var horizontal = bulletml.dsl.horizontal;
var vertical = bulletml.dsl.vertical;
var fireOption = bulletml.dsl.fireOption;
var offsetX = bulletml.dsl.offsetX;
var offsetY = bulletml.dsl.offsetY;
var autonomy = bulletml.dsl.autonomy;

var interval = function(v) {
  return wait("{0} * (0.3 + (1.0 - $densityRank) * 0.7)".format(v));
};
var spd = function(v) {
  return speed("{0} * (1.0 + $speedRank * 2.0)".format(v));
};
var spdSeq = function(v) {
  return speed("{0} * (1.0 + $speedRank * 2.0)".format(v), "sequence");
};

var R0 = bullet({
  type: 4
});
var R1 = bullet({
  type: 5
});
var R2 = bullet({
  type: 6
});
var R3 = bullet({
  type: 7
});
var B4 = bullet({
  type: 8
});
var B5 = bullet({
  type: 9
});
var R4 = bullet({
  type: 10
});
var R5 = bullet({
  type: 11
});
var DM = bullet({
  dummy: true
});

// URwp
var basic = function(s, dir) {
  return new bulletml.Root({
    top: action([
      interval(10),
      repeat(Infinity, [
        fire(DM, spd(s), direction(dir)),
        repeat("$burst + 1", [
          fire(R2, spdSeq(0.15), direction(0, "sequence")),
        ]),
        interval(50),
      ]),
    ]),
  });
};
pbr.danmaku.basic = basic(1, 0);
pbr.danmaku.basicR1 = basic(1, -5);
pbr.danmaku.basicL1 = basic(1, +5);
pbr.danmaku.basicR2 = basic(1, -15);
pbr.danmaku.basicL2 = basic(1, +15);
pbr.danmaku.basicF = basic(1.2, 0);
pbr.danmaku.basicFR1 = basic(1.2, -5);
pbr.danmaku.basicFL1 = basic(1.2, +5);
pbr.danmaku.basicFR2 = basic(1.2, -15);
pbr.danmaku.basicFL2 = basic(1.2, +15);

});

<|endoftext|>


<commit_before><commit_msg>Fix bug with non-directions map sources.<commit_after><|endoftext|>