<commit_before>function initTypeProto(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function initTypeProtoI(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){}//IGNORE
function Character(x){}//IGNORE
function isOfType(a,b){}//IGNORE
function smallest(x,y){}//IGNORE
function largest(x,y){}//IGNORE
function Exception(){}//IGNORE
var List,Some,Cloneable,Ranged,exports,larger,smaller,equal,Object$,$empty,$finished,Iterator;//IGNORE
var IdentifiableObject,Category,Sized;//IGNORE

function Sequence($$sequence) {
    return $$sequence;
}
initTypeProtoI(Sequence, 'ceylon.language::Sequence', Some, Cloneable, Ranged, List);
var Sequence$proto = Sequence.$$.prototype;
Sequence$proto.getLast = function() {
    var last = this.item(this.getLastIndex());
    if (last === null) throw Exception();
    return last;
}

function Array$() {
    var that = new Array$.$$;
    return that;
}
initExistingType(Array$, Array, 'ceylon.language::Array', Object$, FixedSized,
        Cloneable, Ranged, List);
var Array$proto = Array.prototype;
var origArrToString = Array$proto.toString;
inheritProtoI(Array$, Object$, FixedSized, Cloneable, Ranged, List);
Array$proto.toString = origArrToString;
exports.Array=Array$;

function EmptyArray() {
    return [];
}
initTypeProto(EmptyArray, 'ceylon.language::EmptyArray', Array$, None);
function ArrayList(items) {
    return items;
}
initTypeProto(ArrayList, 'ceylon.language::ArrayList', Array$, List);
function ArraySequence(/* js array */value) {
    value.$seq = true;
    return value;
}
initTypeProto(ArraySequence, 'ceylon.language::ArraySequence', IdentifiableObject, Sequence);

Array$proto.getT$name$ = function() {
    return (this.$seq ? ArraySequence : (this.length>0?ArrayList:EmptyArray)).$$.T$name;
}
Array$proto.getT$all$ = function() {
    return (this.$seq ? ArraySequence : (this.length>0?ArrayList:EmptyArray)).$$.T$all;
}

exports.EmptyArray=EmptyArray;

Array$proto.getSize = function() { return this.length; }
Array$proto.setItem = function(idx,elem) {
    if (idx >= 0 && idx < this.length) {
        this[idx] = elem;
    }
}
Array$proto.item = function(idx) {
    var result = this[idx];
    return result!==undefined ? result:null;
}
Array$proto.getLastIndex = function() {
    return this.length>0 ? (this.length-1) : null;
}
Array$proto.getReversed = function() {
    if (this.length === 0) { return this; }
    var arr = this.slice(0);
    arr.reverse();
    return this.$seq ? ArraySequence(arr) : arr;
}
Array$proto.chain = function(other) {
    if (this.length === 0) { return other; }
    return Iterable.$$.prototype.chain.call(this, other);
}
Array$proto.getFirst = function() { return this.length>0 ? this[0] : null; }
Array$proto.getLast = function() { return this.length>0 ? this[this.length-1] : null; }
Array$proto.segment = function(from, len) {
    if (len <= 0) { return $empty; }
    var stop = from + len;
    var seq = this.slice((from>=0)?from:0, (stop>=0)?stop:0);
    return (seq.length > 0) ? ArraySequence(seq) : $empty;
}
Array$proto.span = function(from, to) {
    var toIndex = (to===null || to===undefined) ? 0x7fffffff : to;
    if (from > toIndex) {
        return this.segment(toIndex, from-toIndex+1).getReversed();
    }
    return this.segment(from, toIndex-from+1);
}
Array$proto.getRest = function() {
    return this.length<=1 ? $empty : ArraySequence(this.slice(1));
}
Array$proto.items = function(keys) {
    if (keys === undefined) return $empty;
    var seq = [];
    for (var i = 0; i < keys.getSize(); i++) {
        var key = keys.item(i);
        seq.push(this.item(key));
    }
    return ArraySequence(seq);
}
Array$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language::Integer'); }
Array$proto.contains = function(elem) {
    for (var i=0; i<this.length; i++) {
        if (elem.equals(this[i])) {
            return true;
        }
    }
    return false;
}

exports.ArrayList=ArrayList;
exports.arrayOfNone=function() { return []; }
exports.arrayOfSome=function(/*Sequence*/elems) { //In practice it's an ArraySequence
    return elems;
}
exports.array=function(elems) {
    if (elems === null || elems === undefined) {
        return [];
    } else {
        var e=[];
        var iter=elems.getIterator();
        var item;while((item=iter.next())!==$finished) {
            e.push(item);
        }
        return e;
    }
}
exports.arrayOfSize=function(size, elem) {
    if (size > 0) {
        var elems = [];
        for (var i = 0; i < size; i++) {
            elems.push(elem);
        }
        return elems;
    } else return [];
}

function TypeCategory(seq, type) {
    var that = new TypeCategory.$$;
    that.type = type;
    that.seq = seq;
    return that;
}
initTypeProto(TypeCategory, 'ceylon.language::TypeCategory', IdentifiableObject, Category);
var TypeCategory$proto = TypeCategory.$$.prototype;
TypeCategory$proto.contains = function(k) {
    return isOfType(k, this.type) && this.seq.defines(k);
}

function SequenceBuilder() {
    var that = new SequenceBuilder.$$;
    that.seq = [];
    return that;
}
initTypeProto(SequenceBuilder, 'ceylon.language::SequenceBuilder', IdentifiableObject, Sized);
var SequenceBuilder$proto = SequenceBuilder.$$.prototype;
SequenceBuilder$proto.getSequence = function() { return ArraySequence(this.seq); }
SequenceBuilder$proto.append = function(e) { this.seq.push(e); }
SequenceBuilder$proto.appendAll = function(/*Iterable*/arr) {
    if (arr === undefined) return;
    var iter = arr.getIterator();
    var e; while ((e = iter.next()) !== $finished) {
        this.seq.push(e);
    }
}
SequenceBuilder$proto.getSize = function() { return this.seq.length; }

function SequenceAppender(other) {
    var that = new SequenceAppender.$$;
    that.seq = [];
    that.appendAll(other);
    return that;
}
initTypeProto(SequenceAppender, 'ceylon.language::SequenceAppender', SequenceBuilder);

function Singleton(elem) {
    var that = new Singleton.$$;
    that.value = [elem];
    that.elem = elem;
    return that;
}
initTypeProto(Singleton, 'ceylon.language::Singleton', Object$, Sequence);
var Singleton$proto = Singleton.$$.prototype;
Singleton$proto.getString = function() { return String$("{ " + this.elem.getString() + " }") }
Singleton$proto.item = function(index) {
    return index===0 ? this.value[0] : null;
}
Singleton$proto.getSize = function() { return 1; }
Singleton$proto.getLastIndex = function() { return 0; }
Singleton$proto.getFirst = function() { return this.elem; }
Singleton$proto.getLast = function() { return this.elem; }
Singleton$proto.getEmpty = function() { return false; }
Singleton$proto.getRest = function() { return $empty; }
Singleton$proto.defines = function(idx) { return idx.equals(0); }
Singleton$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language::Integer'); }
Singleton$proto.span = function(from, to) {
    if ((to === undefined) || (to === null)) {
        return (from <= 0) ? this : $empty;
    }
    return (((from <= 0) && (to >= 0)) || ((from >= 0) && (to <= 0))) ? this : $empty;
}
Singleton$proto.segment = function(idx, len) {
    return ((idx <= 0) && ((idx+len) > 0)) ? this : $empty;
}
Singleton$proto.getIterator = function() { return SingletonIterator(this.elem); }
Singleton$proto.getReversed = function() { return this; }
Singleton$proto.equals = function(other) {
    if (isOfType(other, 'ceylon.language::List')) {
        if (other.getSize() !== 1) {
            return false;
        }
        var o = other.item(0);
        return o !== null && o.equals(this.elem);
    }
    return false;
}
Singleton$proto.$map = function(f) { return ArraySequence([ f(this.elem) ]); }
Singleton$proto.$filter = function(f) {
    return f(this.elem) ? this : $empty;
}
Singleton$proto.fold = function(v,f) {
    return f(v, this.elem);
}
Singleton$proto.find = function(f) {
    return f(this.elem) ? this.elem : null;
}
Singleton$proto.findLast = function(f) {
    return f(this.elem) ? this.elem : null;
}
Singleton$proto.any = function(f) {
    return f(this.elem);
}
Singleton$proto.$every = function(f) {
    return f(this.elem);
}
Singleton$proto.skipping = function(skip) {
    return skip==0 ? this : $empty;
}
Singleton$proto.taking = function(take) {
    return take>0 ? this : $empty;
}
Singleton$proto.by = function(step) {
    return this;
}
Singleton$proto.$sort = function(f) { return this; }
Singleton$proto.count = function(f) {
	return f(this.elem) ? 1 : 0;
}
Singleton$proto.contains = function(o) {
	return this.elem.equals(o);
}
Singleton$proto.getCoalesced = function() { return this; }

function SingletonIterator(elem) {
    var that = new SingletonIterator.$$;
    that.elem = elem;
    that.done = false;
    return that;
}
initTypeProto(SingletonIterator, 'ceylon.language::SingletonIterator', IdentifiableObject, Iterator);
var $SingletonIterator$proto = SingletonIterator.$$.prototype;
$SingletonIterator$proto.next = function() {
    if (this.done) {
        return $finished;
    }
    this.done = true;
    return this.elem;
}

exports.Sequence=Sequence;
exports.SequenceBuilder=SequenceBuilder;
exports.SequenceAppender=SequenceAppender;
exports.ArraySequence=ArraySequence;
exports.Singleton=Singleton;
<commit_msg>SequenceBuilder: correct return value for empty sequence<commit_after>function initTypeProto(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function initTypeProtoI(a,b,c,d,e,f,g,h,i,j,k,l);//IGNORE
function String$(x){}//IGNORE
function Character(x){}//IGNORE
function isOfType(a,b){}//IGNORE
function smallest(x,y){}//IGNORE
function largest(x,y){}//IGNORE
function Exception(){}//IGNORE
var List,Some,Cloneable,Ranged,exports,larger,smaller,equal,Object$,$empty,$finished,Iterator;//IGNORE
var IdentifiableObject,Category,Sized;//IGNORE

function Sequence($$sequence) {
    return $$sequence;
}
initTypeProtoI(Sequence, 'ceylon.language::Sequence', Some, Cloneable, Ranged, List);
var Sequence$proto = Sequence.$$.prototype;
Sequence$proto.getLast = function() {
    var last = this.item(this.getLastIndex());
    if (last === null) throw Exception();
    return last;
}

function Array$() {
    var that = new Array$.$$;
    return that;
}
initExistingType(Array$, Array, 'ceylon.language::Array', Object$, FixedSized,
        Cloneable, Ranged, List);
var Array$proto = Array.prototype;
var origArrToString = Array$proto.toString;
inheritProtoI(Array$, Object$, FixedSized, Cloneable, Ranged, List);
Array$proto.toString = origArrToString;
exports.Array=Array$;

function EmptyArray() {
    return [];
}
initTypeProto(EmptyArray, 'ceylon.language::EmptyArray', Array$, None);
function ArrayList(items) {
    return items;
}
initTypeProto(ArrayList, 'ceylon.language::ArrayList', Array$, List);
function ArraySequence(/* js array */value) {
    value.$seq = true;
    return value;
}
initTypeProto(ArraySequence, 'ceylon.language::ArraySequence', IdentifiableObject, Sequence);

Array$proto.getT$name$ = function() {
    return (this.$seq ? ArraySequence : (this.length>0?ArrayList:EmptyArray)).$$.T$name;
}
Array$proto.getT$all$ = function() {
    return (this.$seq ? ArraySequence : (this.length>0?ArrayList:EmptyArray)).$$.T$all;
}

exports.EmptyArray=EmptyArray;

Array$proto.getSize = function() { return this.length; }
Array$proto.setItem = function(idx,elem) {
    if (idx >= 0 && idx < this.length) {
        this[idx] = elem;
    }
}
Array$proto.item = function(idx) {
    var result = this[idx];
    return result!==undefined ? result:null;
}
Array$proto.getLastIndex = function() {
    return this.length>0 ? (this.length-1) : null;
}
Array$proto.getReversed = function() {
    if (this.length === 0) { return this; }
    var arr = this.slice(0);
    arr.reverse();
    return this.$seq ? ArraySequence(arr) : arr;
}
Array$proto.chain = function(other) {
    if (this.length === 0) { return other; }
    return Iterable.$$.prototype.chain.call(this, other);
}
Array$proto.getFirst = function() { return this.length>0 ? this[0] : null; }
Array$proto.getLast = function() { return this.length>0 ? this[this.length-1] : null; }
Array$proto.segment = function(from, len) {
    if (len <= 0) { return $empty; }
    var stop = from + len;
    var seq = this.slice((from>=0)?from:0, (stop>=0)?stop:0);
    return (seq.length > 0) ? ArraySequence(seq) : $empty;
}
Array$proto.span = function(from, to) {
    var toIndex = (to===null || to===undefined) ? 0x7fffffff : to;
    if (from > toIndex) {
        return this.segment(toIndex, from-toIndex+1).getReversed();
    }
    return this.segment(from, toIndex-from+1);
}
Array$proto.getRest = function() {
    return this.length<=1 ? $empty : ArraySequence(this.slice(1));
}
Array$proto.items = function(keys) {
    if (keys === undefined) return $empty;
    var seq = [];
    for (var i = 0; i < keys.getSize(); i++) {
        var key = keys.item(i);
        seq.push(this.item(key));
    }
    return ArraySequence(seq);
}
Array$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language::Integer'); }
Array$proto.contains = function(elem) {
    for (var i=0; i<this.length; i++) {
        if (elem.equals(this[i])) {
            return true;
        }
    }
    return false;
}

exports.ArrayList=ArrayList;
exports.arrayOfNone=function() { return []; }
exports.arrayOfSome=function(/*Sequence*/elems) { //In practice it's an ArraySequence
    return elems;
}
exports.array=function(elems) {
    if (elems === null || elems === undefined) {
        return [];
    } else {
        var e=[];
        var iter=elems.getIterator();
        var item;while((item=iter.next())!==$finished) {
            e.push(item);
        }
        return e;
    }
}
exports.arrayOfSize=function(size, elem) {
    if (size > 0) {
        var elems = [];
        for (var i = 0; i < size; i++) {
            elems.push(elem);
        }
        return elems;
    } else return [];
}

function TypeCategory(seq, type) {
    var that = new TypeCategory.$$;
    that.type = type;
    that.seq = seq;
    return that;
}
initTypeProto(TypeCategory, 'ceylon.language::TypeCategory', IdentifiableObject, Category);
var TypeCategory$proto = TypeCategory.$$.prototype;
TypeCategory$proto.contains = function(k) {
    return isOfType(k, this.type) && this.seq.defines(k);
}

function SequenceBuilder() {
    var that = new SequenceBuilder.$$;
    that.seq = [];
    return that;
}
initTypeProto(SequenceBuilder, 'ceylon.language::SequenceBuilder', IdentifiableObject, Sized);
var SequenceBuilder$proto = SequenceBuilder.$$.prototype;
SequenceBuilder$proto.getSequence = function() {
    return (this.seq.length > 0) ? ArraySequence(this.seq) : $empty;
}
SequenceBuilder$proto.append = function(e) { this.seq.push(e); }
SequenceBuilder$proto.appendAll = function(/*Iterable*/arr) {
    if (arr === undefined) return;
    var iter = arr.getIterator();
    var e; while ((e = iter.next()) !== $finished) {
        this.seq.push(e);
    }
}
SequenceBuilder$proto.getSize = function() { return this.seq.length; }

function SequenceAppender(other) {
    var that = new SequenceAppender.$$;
    that.seq = [];
    that.appendAll(other);
    return that;
}
initTypeProto(SequenceAppender, 'ceylon.language::SequenceAppender', SequenceBuilder);

function Singleton(elem) {
    var that = new Singleton.$$;
    that.value = [elem];
    that.elem = elem;
    return that;
}
initTypeProto(Singleton, 'ceylon.language::Singleton', Object$, Sequence);
var Singleton$proto = Singleton.$$.prototype;
Singleton$proto.getString = function() { return String$("{ " + this.elem.getString() + " }") }
Singleton$proto.item = function(index) {
    return index===0 ? this.value[0] : null;
}
Singleton$proto.getSize = function() { return 1; }
Singleton$proto.getLastIndex = function() { return 0; }
Singleton$proto.getFirst = function() { return this.elem; }
Singleton$proto.getLast = function() { return this.elem; }
Singleton$proto.getEmpty = function() { return false; }
Singleton$proto.getRest = function() { return $empty; }
Singleton$proto.defines = function(idx) { return idx.equals(0); }
Singleton$proto.getKeys = function() { return TypeCategory(this, 'ceylon.language::Integer'); }
Singleton$proto.span = function(from, to) {
    if ((to === undefined) || (to === null)) {
        return (from <= 0) ? this : $empty;
    }
    return (((from <= 0) && (to >= 0)) || ((from >= 0) && (to <= 0))) ? this : $empty;
}
Singleton$proto.segment = function(idx, len) {
    return ((idx <= 0) && ((idx+len) > 0)) ? this : $empty;
}
Singleton$proto.getIterator = function() { return SingletonIterator(this.elem); }
Singleton$proto.getReversed = function() { return this; }
Singleton$proto.equals = function(other) {
    if (isOfType(other, 'ceylon.language::List')) {
        if (other.getSize() !== 1) {
            return false;
        }
        var o = other.item(0);
        return o !== null && o.equals(this.elem);
    }
    return false;
}
Singleton$proto.$map = function(f) { return ArraySequence([ f(this.elem) ]); }
Singleton$proto.$filter = function(f) {
    return f(this.elem) ? this : $empty;
}
Singleton$proto.fold = function(v,f) {
    return f(v, this.elem);
}
Singleton$proto.find = function(f) {
    return f(this.elem) ? this.elem : null;
}
Singleton$proto.findLast = function(f) {
    return f(this.elem) ? this.elem : null;
}
Singleton$proto.any = function(f) {
    return f(this.elem);
}
Singleton$proto.$every = function(f) {
    return f(this.elem);
}
Singleton$proto.skipping = function(skip) {
    return skip==0 ? this : $empty;
}
Singleton$proto.taking = function(take) {
    return take>0 ? this : $empty;
}
Singleton$proto.by = function(step) {
    return this;
}
Singleton$proto.$sort = function(f) { return this; }
Singleton$proto.count = function(f) {
	return f(this.elem) ? 1 : 0;
}
Singleton$proto.contains = function(o) {
	return this.elem.equals(o);
}
Singleton$proto.getCoalesced = function() { return this; }

function SingletonIterator(elem) {
    var that = new SingletonIterator.$$;
    that.elem = elem;
    that.done = false;
    return that;
}
initTypeProto(SingletonIterator, 'ceylon.language::SingletonIterator', IdentifiableObject, Iterator);
var $SingletonIterator$proto = SingletonIterator.$$.prototype;
$SingletonIterator$proto.next = function() {
    if (this.done) {
        return $finished;
    }
    this.done = true;
    return this.elem;
}

exports.Sequence=Sequence;
exports.SequenceBuilder=SequenceBuilder;
exports.SequenceAppender=SequenceAppender;
exports.ArraySequence=ArraySequence;
exports.Singleton=Singleton;
<|endoftext|>


<commit_before>import Trilogy from 'trilogy';
import path from 'path';
import fs from 'fs';
import log from 'karmapa-log';
import {indexBy, prop} from 'ramda';

import APP_DATA_PATH from './../constants/appDataPath';

// if db version change, user will have to convert their db via online tool
const dbVersion = '0.0.11';

export default async function initDb() {

  const dbPath = path.resolve(APP_DATA_PATH, `garchen-panel-${dbVersion}.db`);

  try {
    fs.closeSync(fs.openSync(dbPath, 'wx'));
    log.info('Created db file.');
  }
  catch (err) {
    log.info('DB file already existed, skip creating file.');
  }

  const options = {client: 'sqlite3'};

  if ('development' === process.env.LOG_QUERY) {
    options.verbose = (sql) => log.info(`sql: ${sql}`);
  }

  const db = new Trilogy(dbPath, options);

  const promises = fs.readdirSync(__dirname)
    .filter((filename) => (0 !== filename.indexOf('.')) && ('index.js' !== filename))
    .map((filename) => {
      const {name, schema, options} = require(path.resolve(__dirname, filename));
      return db.model(name, schema, options);
    });

  const models = indexBy(prop('name'), (await Promise.all(promises)));
  return {db, models};
}
<commit_msg>change dbVersion from 0.0.11 to 0.0.12<commit_after>import Trilogy from 'trilogy';
import path from 'path';
import fs from 'fs';
import log from 'karmapa-log';
import {indexBy, prop} from 'ramda';

import APP_DATA_PATH from './../constants/appDataPath';

// if db version change, user will have to convert their db via online tool
const dbVersion = '0.0.12';

export default async function initDb() {

  const dbPath = path.resolve(APP_DATA_PATH, `garchen-panel-${dbVersion}.db`);

  try {
    fs.closeSync(fs.openSync(dbPath, 'wx'));
    log.info('Created db file.');
  }
  catch (err) {
    log.info('DB file already existed, skip creating file.');
  }

  const options = {client: 'sqlite3'};

  if ('development' === process.env.LOG_QUERY) {
    options.verbose = (sql) => log.info(`sql: ${sql}`);
  }

  const db = new Trilogy(dbPath, options);

  const promises = fs.readdirSync(__dirname)
    .filter((filename) => (0 !== filename.indexOf('.')) && ('index.js' !== filename))
    .map((filename) => {
      const {name, schema, options} = require(path.resolve(__dirname, filename));
      return db.model(name, schema, options);
    });

  const models = indexBy(prop('name'), (await Promise.all(promises)));
  return {db, models};
}
<|endoftext|>


<commit_before>/*
 * Minio Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015, 2016 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as xmlParsers from './xml-parsers.js'
import * as _ from 'lodash'
import Through2 from 'through2'
import Crypto from 'crypto';

import { isFunction } from './helpers.js'
import * as errors from './errors.js'

// getConcater returns a stream that concatenates the input and emits
// the concatenated output when 'end' has reached. If an optional
// parser function is passed upon reaching the 'end' of the stream,
// `parser(concatenated_data)` will be emitted.
export function getConcater(parser, emitError) {
  var objectMode = false
  var bufs = []

  if (parser && !isFunction(parser)) {
    throw new TypeError('parser should be of type "function"')
  }

  if (parser) {
    objectMode = true
  }

  return Through2({objectMode},
  function (chunk, enc, cb) {
    bufs.push(chunk)
    cb()
  }, function (cb) {
    if (emitError) {
      cb(parser(Buffer.concat(bufs).toString()))
      // cb(e) would mean we have to emit 'end' by explicitly calling this.push(null)
      this.push(null)
      return
    }
    if (bufs.length) {
      if (parser) {
        this.push(parser(Buffer.concat(bufs).toString()))
      } else {
        this.push(Buffer.concat(bufs))
      }
    }
    cb()
  })
}

// Generates an Error object depending on http statusCode and XML body
export function getErrorTransformer(response) {
  var statusCode = response.statusCode
  var code, message
  if (statusCode === 301) {
    code = 'MovedPermanently'
    message = 'Moved Permanently'
  } else if (statusCode === 307) {
    code = 'TemporaryRedirect'
    message = 'Are you using the correct endpoint URL?'
  } else if (statusCode === 403) {
    code = 'AccessDenied'
    message = 'Valid and authorized credentials required'
  } else if (statusCode === 404) {
    code = 'NotFound'
    message = 'Not Found'
  } else if (statusCode === 405) {
    code = 'MethodNotAllowed'
    message = 'Method Not Allowed'
  } else if (statusCode === 501) {
    code = 'MethodNotAllowed'
    message = 'Method Not Allowed'
  } else {
    code = 'UnknownError'
    message = `${statusCode}`
  }

  var headerInfo = {}
  // A value created by S3 compatible server that uniquely identifies
  // the request.
  headerInfo.amzRequestid = response.headersSent ? response.getHeader('x-amz-request-id') : null
  // A special token that helps troubleshoot API replies and issues.
  headerInfo.amzId2 = response.headersSent ? response.getHeader('x-amz-id-2') : null
  // Region where the bucket is located. This header is returned only
  // in HEAD bucket and ListObjects response.
  headerInfo.amzBucketRegion = response.headersSent ? response.getHeader('x-amz-bucket-region') : null

  return getConcater(xmlString => {
    if (!xmlString) {
      // Message should be instantiated for each S3Errors.
      var e = new errors.S3Error(message)
      // S3 Error code.
      e.code = code
      _.each(headerInfo, (value, key) => {
        e[key] = value
      })
      return e
    }
    return xmlParsers.parseError(xmlString, headerInfo)
  }, true)
}

// Makes sure that only size number of bytes go through this stream
export function getSizeLimiter(size, stream, chunker) {
  var sizeRemaining = size
  return Through2.obj(function(chunk, enc, cb) {
    var length = Math.min(chunk.length, sizeRemaining)
    // We should read only till 'size'
    if (length < chunk.length) chunk = chunk.slice(0, length)
    this.push(chunk)
    sizeRemaining -= length
    if (sizeRemaining === 0) {
      // Unpipe so that the streams do not send us more data
      stream.unpipe()
      chunker.unpipe()
      this.push(null)
    }
    cb()
  }, function(cb) {
    if (sizeRemaining !== 0) {
      return cb(new errors.IncorrectSizeError('size of the input stream is not equal to the expected size(${size})'))
    }
    this.push(null)
    cb()
  })
}

// A through stream that calculates md5sum and sha256sum
export function getHashSummer(anonymous) {
  var md5 = Crypto.createHash('md5')
  var sha256 = Crypto.createHash('sha256')

  return Through2.obj(function(chunk, enc, cb) {
    md5.update(chunk)
    if (!anonymous) sha256.update(chunk)
    cb()
  }, function(cb) {
    var md5sum = md5.digest('base64')
    var hashData = {md5sum}
    if (!anonymous) hashData.sha256sum = sha256.digest('hex')
    this.push(hashData)
    this.push(null)
  })
}

// Following functions return a stream object that parses XML
// and emits suitable Javascript objects.

// Parses listBuckets response.
export function getListBucketTransformer() {
  return getConcater(xmlParsers.parseListBucket)
}

// Parses listMultipartUploads response.
export function getListMultipartTransformer() {
  return getConcater(xmlParsers.parseListMultipart)
}

// Parses listParts response.
export function getListPartsTransformer() {
  return getConcater(xmlParsers.parseListParts)
}

// Parses getBucketACL response.
export function getAclTransformer() {
  return getConcater(xmlParsers.parseAcl)
}

// Parses initMultipartUpload response.
export function getInitiateMultipartTransformer() {
  return getConcater(xmlParsers.parseInitiateMultipart)
}

// Parses listObjects response.
export function getListObjectsTransformer() {
  return getConcater(xmlParsers.parseListObjects)
}

// Parses completeMultipartUpload response.
export function getCompleteMultipartTransformer() {
  return getConcater(xmlParsers.parseCompleteMultipart)
}

// Parses getBucketLocation response.
export function getBucketRegionTransformer() {
  return getConcater(xmlParsers.parseBucketRegion)
}
<commit_msg>Update transformers.js (#434)<commit_after>/*
 * Minio Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015, 2016 Minio, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as xmlParsers from './xml-parsers.js'
import * as _ from 'lodash'
import Through2 from 'through2'
import Crypto from 'crypto';

import { isFunction } from './helpers.js'
import * as errors from './errors.js'

// getConcater returns a stream that concatenates the input and emits
// the concatenated output when 'end' has reached. If an optional
// parser function is passed upon reaching the 'end' of the stream,
// `parser(concatenated_data)` will be emitted.
export function getConcater(parser, emitError) {
  var objectMode = false
  var bufs = []

  if (parser && !isFunction(parser)) {
    throw new TypeError('parser should be of type "function"')
  }

  if (parser) {
    objectMode = true
  }

  return Through2({objectMode},
  function (chunk, enc, cb) {
    bufs.push(chunk)
    cb()
  }, function (cb) {
    if (emitError) {
      cb(parser(Buffer.concat(bufs).toString()))
      // cb(e) would mean we have to emit 'end' by explicitly calling this.push(null)
      this.push(null)
      return
    }
    if (bufs.length) {
      if (parser) {
        this.push(parser(Buffer.concat(bufs).toString()))
      } else {
        this.push(Buffer.concat(bufs))
      }
    }
    cb()
  })
}

// Generates an Error object depending on http statusCode and XML body
export function getErrorTransformer(response) {
  var statusCode = response.statusCode
  var code, message
  if (statusCode === 301) {
    code = 'MovedPermanently'
    message = 'Moved Permanently'
  } else if (statusCode === 307) {
    code = 'TemporaryRedirect'
    message = 'Are you using the correct endpoint URL?'
  } else if (statusCode === 403) {
    code = 'AccessDenied'
    message = 'Valid and authorized credentials required'
  } else if (statusCode === 404) {
    code = 'NotFound'
    message = 'Not Found'
  } else if (statusCode === 405) {
    code = 'MethodNotAllowed'
    message = 'Method Not Allowed'
  } else if (statusCode === 501) {
    code = 'MethodNotAllowed'
    message = 'Method Not Allowed'
  } else {
    code = 'UnknownError'
    message = `${statusCode}`
  }

  var headerInfo = {}
  // A value created by S3 compatible server that uniquely identifies
  // the request.
  headerInfo.amzRequestid = response.headersSent ? response.getHeader('x-amz-request-id') : null
  // A special token that helps troubleshoot API replies and issues.
  headerInfo.amzId2 = response.headersSent ? response.getHeader('x-amz-id-2') : null
  // Region where the bucket is located. This header is returned only
  // in HEAD bucket and ListObjects response.
  headerInfo.amzBucketRegion = response.headersSent ? response.getHeader('x-amz-bucket-region') : null

  return getConcater(xmlString => {
    if (!xmlString) {
      // Message should be instantiated for each S3Errors.
      var e = new errors.S3Error(message)
      // S3 Error code.
      e.code = code
      _.each(headerInfo, (value, key) => {
        e[key] = value
      })
      return e
    }
    return xmlParsers.parseError(xmlString, headerInfo)
  }, true)
}

// Makes sure that only size number of bytes go through this stream
export function getSizeLimiter(size, stream, chunker) {
  var sizeRemaining = size
  return Through2.obj(function(chunk, enc, cb) {
    var length = Math.min(chunk.length, sizeRemaining)
    // We should read only till 'size'
    if (length < chunk.length) chunk = chunk.slice(0, length)
    this.push(chunk)
    sizeRemaining -= length
    if (sizeRemaining === 0) {
      // Unpipe so that the streams do not send us more data
      stream.unpipe()
      chunker.unpipe()
      this.push(null)
    }
    cb()
  }, function(cb) {
    if (sizeRemaining !== 0) {
      return cb(new errors.IncorrectSizeError(`size of the input stream is not equal to the expected size(${size})`))
    }
    this.push(null)
    cb()
  })
}

// A through stream that calculates md5sum and sha256sum
export function getHashSummer(anonymous) {
  var md5 = Crypto.createHash('md5')
  var sha256 = Crypto.createHash('sha256')

  return Through2.obj(function(chunk, enc, cb) {
    md5.update(chunk)
    if (!anonymous) sha256.update(chunk)
    cb()
  }, function(cb) {
    var md5sum = md5.digest('base64')
    var hashData = {md5sum}
    if (!anonymous) hashData.sha256sum = sha256.digest('hex')
    this.push(hashData)
    this.push(null)
  })
}

// Following functions return a stream object that parses XML
// and emits suitable Javascript objects.

// Parses listBuckets response.
export function getListBucketTransformer() {
  return getConcater(xmlParsers.parseListBucket)
}

// Parses listMultipartUploads response.
export function getListMultipartTransformer() {
  return getConcater(xmlParsers.parseListMultipart)
}

// Parses listParts response.
export function getListPartsTransformer() {
  return getConcater(xmlParsers.parseListParts)
}

// Parses getBucketACL response.
export function getAclTransformer() {
  return getConcater(xmlParsers.parseAcl)
}

// Parses initMultipartUpload response.
export function getInitiateMultipartTransformer() {
  return getConcater(xmlParsers.parseInitiateMultipart)
}

// Parses listObjects response.
export function getListObjectsTransformer() {
  return getConcater(xmlParsers.parseListObjects)
}

// Parses completeMultipartUpload response.
export function getCompleteMultipartTransformer() {
  return getConcater(xmlParsers.parseCompleteMultipart)
}

// Parses getBucketLocation response.
export function getBucketRegionTransformer() {
  return getConcater(xmlParsers.parseBucketRegion)
}
<|endoftext|>


<commit_before>var main = module.exports = {
  dispatch,
  hide,
  init,
  send,
  setAspectRatio,
  setBounds,
  setProgress,
  setTitle,
  show,
  toggleAlwaysOnTop,
  toggleDevTools,
  toggleFullScreen,
  win: null
}

var electron = require('electron')

var app = electron.app

var config = require('../../config')
var log = require('../log')
var menu = require('../menu')
var tray = require('../tray')

var HEADER_HEIGHT = 37
var TORRENT_HEIGHT = 100

function init () {
  if (main.win) {
    return main.win.show()
  }
  var win = main.win = new electron.BrowserWindow({
    backgroundColor: '#1E1E1E',
    darkTheme: true, // Forces dark theme (GTK+3)
    icon: getIconPath(), // Window icon (Windows, Linux)
    minWidth: config.WINDOW_MIN_WIDTH,
    minHeight: config.WINDOW_MIN_HEIGHT,
    title: config.APP_WINDOW_TITLE,
    titleBarStyle: 'hidden-inset', // Hide title bar (Mac)
    useContentSize: true, // Specify web page size without OS chrome
    width: 500,
    height: HEADER_HEIGHT + (TORRENT_HEIGHT * 6) // header height + 5 torrents
  })

  win.loadURL(config.WINDOW_MAIN)

  if (win.setSheetOffset) win.setSheetOffset(HEADER_HEIGHT)

  win.webContents.on('dom-ready', function () {
    menu.onToggleFullScreen(main.win.isFullScreen())
  })

  win.on('blur', onWindowBlur)
  win.on('focus', onWindowFocus)

  win.on('hide', onWindowBlur)
  win.on('show', onWindowFocus)

  win.on('enter-full-screen', function () {
    menu.onToggleFullScreen(true)
    send('fullscreenChanged', true)
    win.setMenuBarVisibility(false)
  })

  win.on('leave-full-screen', function () {
    menu.onToggleFullScreen(false)
    send('fullscreenChanged', false)
    win.setMenuBarVisibility(true)
  })

  win.on('close', function (e) {
    if (process.platform !== 'darwin' && !tray.hasTray()) {
      app.quit()
    } else if (!app.isQuitting) {
      e.preventDefault()
      hide()
    }
  })
}

function dispatch (...args) {
  send('dispatch', ...args)
}

function hide () {
  if (!main.win) return
  main.win.send('dispatch', 'backToList')
  main.win.hide()
}

function send (...args) {
  if (!main.win) return
  main.win.send(...args)
}

/**
 * Enforce window aspect ratio. Remove with 0. (Mac)
 */
function setAspectRatio (aspectRatio) {
  if (!main.win) return
  main.win.setAspectRatio(aspectRatio)
}

/**
 * Change the size of the window.
 * TODO: Clean this up? Seems overly complicated.
 */
function setBounds (bounds, maximize) {
  // Do nothing in fullscreen
  if (!main.win || main.win.isFullScreen()) {
    log('setBounds: not setting bounds because we\'re in full screen')
    return
  }

  // Maximize or minimize, if the second argument is present
  var willBeMaximized
  if (maximize === true) {
    if (!main.win.isMaximized()) {
      log('setBounds: maximizing')
      main.win.maximize()
    }
    willBeMaximized = true
  } else if (maximize === false) {
    if (main.win.isMaximized()) {
      log('setBounds: unmaximizing')
      main.win.unmaximize()
    }
    willBeMaximized = false
  } else {
    willBeMaximized = main.win.isMaximized()
  }

  // Assuming we're not maximized or maximizing, set the window size
  if (!willBeMaximized) {
    log('setBounds: setting bounds to ' + JSON.stringify(bounds))
    if (bounds.x === null && bounds.y === null) {
      // X and Y not specified? By default, center on current screen
      var scr = electron.screen.getDisplayMatching(main.win.getBounds())
      bounds.x = Math.round(scr.bounds.x + scr.bounds.width / 2 - bounds.width / 2)
      bounds.y = Math.round(scr.bounds.y + scr.bounds.height / 2 - bounds.height / 2)
      log('setBounds: centered to ' + JSON.stringify(bounds))
    }
    main.win.setBounds(bounds, true)
  } else {
    log('setBounds: not setting bounds because of window maximization')
  }
}

/**
 * Set progress bar to [0, 1]. Indeterminate when > 1. Remove with < 0.
 */
function setProgress (progress) {
  if (!main.win) return
  main.win.setProgressBar(progress)
}

function setTitle (title) {
  if (!main.win) return
  main.win.setTitle(title)
}

function show () {
  if (!main.win) return
  main.win.show()
}

// Sets whether the window should always show on top of other windows
function toggleAlwaysOnTop (flag) {
  if (!main.win) return
  if (flag == null) {
    flag = !main.win.isAlwaysOnTop()
  }
  log(`toggleAlwaysOnTop ${flag}`)
  main.win.setAlwaysOnTop(flag)
  menu.onToggleAlwaysOnTop(flag)
}

function toggleDevTools () {
  if (!main.win) return
  log('toggleDevTools')
  if (main.win.webContents.isDevToolsOpened()) {
    main.win.webContents.closeDevTools()
  } else {
    main.win.webContents.openDevTools({ detach: true })
  }
}

function toggleFullScreen (flag) {
  if (!main.win || !main.win.isVisible()) {
    return
  }

  if (flag == null) flag = !main.win.isFullScreen()

  log(`toggleFullScreen ${flag}`)

  if (flag) {
    // Fullscreen and aspect ratio do not play well together. (Mac)
    main.win.setAspectRatio(0)
  }

  main.win.setFullScreen(flag)
}

function onWindowBlur () {
  menu.onWindowBlur()
  tray.onWindowBlur()
}

function onWindowFocus () {
  menu.onWindowFocus()
  tray.onWindowFocus()
}

function getIconPath () {
  return process.platform === 'win32'
    ? config.APP_ICON + '.ico'
    : config.APP_ICON + '.png'
}
<commit_msg>Resize the window's content area<commit_after>var main = module.exports = {
  dispatch,
  hide,
  init,
  send,
  setAspectRatio,
  setBounds,
  setProgress,
  setTitle,
  show,
  toggleAlwaysOnTop,
  toggleDevTools,
  toggleFullScreen,
  win: null
}

var electron = require('electron')

var app = electron.app

var config = require('../../config')
var log = require('../log')
var menu = require('../menu')
var tray = require('../tray')

var HEADER_HEIGHT = 37
var TORRENT_HEIGHT = 100

function init () {
  if (main.win) {
    return main.win.show()
  }
  var win = main.win = new electron.BrowserWindow({
    backgroundColor: '#1E1E1E',
    darkTheme: true, // Forces dark theme (GTK+3)
    icon: getIconPath(), // Window icon (Windows, Linux)
    minWidth: config.WINDOW_MIN_WIDTH,
    minHeight: config.WINDOW_MIN_HEIGHT,
    title: config.APP_WINDOW_TITLE,
    titleBarStyle: 'hidden-inset', // Hide title bar (Mac)
    useContentSize: true, // Specify web page size without OS chrome
    width: 500,
    height: HEADER_HEIGHT + (TORRENT_HEIGHT * 6) // header height + 5 torrents
  })

  win.loadURL(config.WINDOW_MAIN)

  if (win.setSheetOffset) win.setSheetOffset(HEADER_HEIGHT)

  win.webContents.on('dom-ready', function () {
    menu.onToggleFullScreen(main.win.isFullScreen())
  })

  win.on('blur', onWindowBlur)
  win.on('focus', onWindowFocus)

  win.on('hide', onWindowBlur)
  win.on('show', onWindowFocus)

  win.on('enter-full-screen', function () {
    menu.onToggleFullScreen(true)
    send('fullscreenChanged', true)
    win.setMenuBarVisibility(false)
  })

  win.on('leave-full-screen', function () {
    menu.onToggleFullScreen(false)
    send('fullscreenChanged', false)
    win.setMenuBarVisibility(true)
  })

  win.on('close', function (e) {
    if (process.platform !== 'darwin' && !tray.hasTray()) {
      app.quit()
    } else if (!app.isQuitting) {
      e.preventDefault()
      hide()
    }
  })
}

function dispatch (...args) {
  send('dispatch', ...args)
}

function hide () {
  if (!main.win) return
  main.win.send('dispatch', 'backToList')
  main.win.hide()
}

function send (...args) {
  if (!main.win) return
  main.win.send(...args)
}

/**
 * Enforce window aspect ratio. Remove with 0. (Mac)
 */
function setAspectRatio (aspectRatio) {
  if (!main.win) return
  main.win.setAspectRatio(aspectRatio)
}

/**
 * Change the size of the window.
 * TODO: Clean this up? Seems overly complicated.
 */
function setBounds (bounds, maximize) {
  // Do nothing in fullscreen
  if (!main.win || main.win.isFullScreen()) {
    log('setBounds: not setting bounds because we\'re in full screen')
    return
  }

  // Maximize or minimize, if the second argument is present
  var willBeMaximized
  if (maximize === true) {
    if (!main.win.isMaximized()) {
      log('setBounds: maximizing')
      main.win.maximize()
    }
    willBeMaximized = true
  } else if (maximize === false) {
    if (main.win.isMaximized()) {
      log('setBounds: unmaximizing')
      main.win.unmaximize()
    }
    willBeMaximized = false
  } else {
    willBeMaximized = main.win.isMaximized()
  }

  // Assuming we're not maximized or maximizing, set the window size
  if (!willBeMaximized) {
    log('setBounds: setting bounds to ' + JSON.stringify(bounds))
    if (bounds.x === null && bounds.y === null) {
      // X and Y not specified? By default, center on current screen
      var scr = electron.screen.getDisplayMatching(main.win.getBounds())
      bounds.x = Math.round(scr.bounds.x + scr.bounds.width / 2 - bounds.width / 2)
      bounds.y = Math.round(scr.bounds.y + scr.bounds.height / 2 - bounds.height / 2)
      log('setBounds: centered to ' + JSON.stringify(bounds))
    }
    // Resize the window's content area (so window border doesn't need to be taken
    // into account)
    main.win.setContentBounds(bounds, true)
  } else {
    log('setBounds: not setting bounds because of window maximization')
  }
}

/**
 * Set progress bar to [0, 1]. Indeterminate when > 1. Remove with < 0.
 */
function setProgress (progress) {
  if (!main.win) return
  main.win.setProgressBar(progress)
}

function setTitle (title) {
  if (!main.win) return
  main.win.setTitle(title)
}

function show () {
  if (!main.win) return
  main.win.show()
}

// Sets whether the window should always show on top of other windows
function toggleAlwaysOnTop (flag) {
  if (!main.win) return
  if (flag == null) {
    flag = !main.win.isAlwaysOnTop()
  }
  log(`toggleAlwaysOnTop ${flag}`)
  main.win.setAlwaysOnTop(flag)
  menu.onToggleAlwaysOnTop(flag)
}

function toggleDevTools () {
  if (!main.win) return
  log('toggleDevTools')
  if (main.win.webContents.isDevToolsOpened()) {
    main.win.webContents.closeDevTools()
  } else {
    main.win.webContents.openDevTools({ detach: true })
  }
}

function toggleFullScreen (flag) {
  if (!main.win || !main.win.isVisible()) {
    return
  }

  if (flag == null) flag = !main.win.isFullScreen()

  log(`toggleFullScreen ${flag}`)

  if (flag) {
    // Fullscreen and aspect ratio do not play well together. (Mac)
    main.win.setAspectRatio(0)
  }

  main.win.setFullScreen(flag)
}

function onWindowBlur () {
  menu.onWindowBlur()
  tray.onWindowBlur()
}

function onWindowFocus () {
  menu.onWindowFocus()
  tray.onWindowFocus()
}

function getIconPath () {
  return process.platform === 'win32'
    ? config.APP_ICON + '.ico'
    : config.APP_ICON + '.png'
}
<|endoftext|>


<commit_before>describe('Math/average', function () {
  it('calculates the average of a set of numbers', function () {
    expect(average()).toEqual(0);

    expect(average(7)).toEqual(7);

    expect(average(2, 4)).toEqual(3);

    expect(average([2, 4])).toEqual(3);

    expect(average(5, 10, 50, -45, 6, 7)).toEqual(5.5);

    expect(average(5, 4, null, true, '12', Infinity)).toEqual(4.5);
  });
});
<commit_msg>add more tests<commit_after>describe('Math/average', function () {
  it('calculates the average of a set of numbers', function () {
    expect(average(5, 10, 50, -45, 6, 7)).toBe(5.5);
    expect(average([5, 10, 50, -45, 6, 7])).toBe(5.5);

    expect(average(2, 4, 0, -0)).toBe(1.5);
    expect(average([2, 4, 0, -0])).toBe(1.5);

    expect(average(7)).toBe(7);
    expect(average([7])).toBe(7);

    expect(average(0, -0)).toBe(0);
    expect(average([0, -0])).toBe(0);

    expect(average()).toBe(0);
    expect(average([])).toBe(0);

    expect(average(Infinity, -Infinity, 0, -0, null, NaN, undefined, false, true, 'foo')).toBe(0);
    expect(average([Infinity, -Infinity, 0, -0, null, NaN, undefined, false, true, 'foo'])).toBe(0);

    expect(average(5, 4, null, true, '12', Infinity)).toBe(4.5);
    expect(average([5, 4, null, true, '12', Infinity])).toBe(4.5);

    expect(average([], {})).toBe(0);
    expect(average([[], {}])).toBe(0);

    expect(average('4', '2')).toBe(0);
    expect(average(['4', '2'])).toBe(0);
  });
});
<|endoftext|>


<commit_before>const {basename, dirname, extname} = require("path")
const {readdir, stat} = require("fs")
const resolve = require("path").resolve

const once = require("once")

const Artist = require("./models/artist.js")
const Cover = require("./models/cover.js")
const Multitrack = require("./models/album-multi.js")
const Singletrack = require("./models/album-single.js")
const Track = require("./models/track.js")

const roots = [
  "/Users/ogd/Music/flac"
]

const cruft = [
  ".DS_Store", // OS X metadata is very cluttery
  "Thumbs.db"  // yes, I do run Windows sometimes
]

const cues = new Map()

function readRoot (root, cb_) {
  let cb = once(cb_)

  readdir(root, function (error, entries) {
    if (error) return cb(error)

    const artists = []

    let i = entries.length
    entries.forEach(function (entry) {
      if (cruft.indexOf(entry) !== -1) {
        --i
        return next()
      }

      stat(resolve(root, entry), function (error, stats) {
        if (error) return cb(error)

        if (stats.isDirectory()) {
          readArtist(root, entry, function (error, artist) {
            if (error) return cb(error)

            --i
            artists.push(artist)

            next()
          })
        }
        else {
          --i
          next()
        }
      })
    })

    function next () {
      if (i === 0) cb(null, artists, artists.reduce((t, a) => t.concat(a.albums), []))
    }
  })
}

function readArtist (root, directory, cb_) {
  const cb = once(cb_)
  const artistPath = resolve(root, directory)
  readdir(artistPath, function (error, entries) {
    if (error) return cb(error)

    const albums = []

    let i = entries.length
    entries.forEach(function (entry) {
      if (cruft.indexOf(entry) !== -1) {
        --i
        return next()
      }

      const currentPath = resolve(artistPath, entry)
      stat(currentPath, function (error, stats) {
        if (error) return cb(error)

        if (stats.isDirectory()) {
          readAlbum(root, directory, entry, function (error, album) {
            if (error) return cb(error)

            --i
            albums.push(album)
            next()
          })
        }
        else if (stats.isFile()) {
          --i
          const ext = extname(entry)
          const base = resolve(artistPath, basename(entry, ext))
          switch (ext) {
            case ".flac":
            case ".mp3":
              albums.push(new Singletrack(
                entry,
                directory,
                currentPath,
                stats
              ))
              break
            case ".cue":
              cues.set(base, currentPath)
              break
            case ".log":
              // nothing to do with these
              break
            default:
              console.log("not sure what to do", entry)
          }
          next()
        }
        else {
          i--
          console.log("rando in artist directory:", directory, entry)
        }
      })
    })

    function next () {
      if (i > 0) return

      albums.forEach((a) => {
        const p = a.path
        const ext = extname(p)
        const base = resolve(dirname(p), basename(p, ext))
        if (cues.get(base)) a.cuesheet = cues.get(base)
      })
      cb(null, new Artist(directory, albums))
    }
  })
}

function readAlbum (root, artist, album, cb_) {
  const cb = once(cb_)

  const albumPath = resolve(root, artist, album)
  readdir(albumPath, function (error, entries) {
    if (error) return cb(error)

    const tracks = []
    const covers = []

    let i = entries.length
    entries.forEach(function (entry) {
      if (cruft.indexOf(entry) !== -1) {
        i--
        return next()
      }

      stat(resolve(albumPath, entry), function (error, stats) {
        if (stats.isDirectory()) {
          i--
          console.log("witaf. what is a directory doing here?", entry)
          next()
        }
        else if (stats.isFile()) {
          i--
          switch (extname(entry)) {
            case ".flac":
            case ".mp3":
              tracks.push(new Track(
                artist,
                album,
                entry,
                stats
              ))
              break
            case ".jpg":
            case ".pdf":
            case ".png":
              covers.push(new Cover(
                resolve(albumPath, entry),
                stats
              ))
              break
            default:
              console.log("I dunno, boss", entry)
          }
          next()
        }
        else {
          i--
          console.log("what", entry)
          next()
        }
      })
    })

    function next () {
      if (i > 0) return

      const a = new Multitrack(album, artist, albumPath, tracks)
      if (covers.length) a.pictures = covers

      cb(null, a)
    }
  })
}

readRoot(roots[0], function (error, artists, albums) {
  if (error) throw error

  albums.forEach((a) => console.log("%s - %s [%s]", a.artist, a.name, a.getSize(1024 * 1024)))
  artists.forEach((a) => console.log("%s [%s]", a.name, a.getSize(1024 * 1024)))
})
<commit_msg>forEach -> for...of<commit_after>const {basename, dirname, extname} = require("path")
const {readdir, stat} = require("fs")
const resolve = require("path").resolve

const once = require("once")

const Artist = require("./models/artist.js")
const Cover = require("./models/cover.js")
const Multitrack = require("./models/album-multi.js")
const Singletrack = require("./models/album-single.js")
const Track = require("./models/track.js")

const roots = [
  "/Users/ogd/Music/flac"
]

const cruft = [
  ".DS_Store", // OS X metadata is very cluttery
  "Thumbs.db"  // yes, I do run Windows sometimes
]

const cues = new Map()

function readRoot (root, cb_) {
  let cb = once(cb_)

  readdir(root, function (error, entries) {
    if (error) return cb(error)

    const artists = []

    let i = entries.length
    for (let entry of entries) {
      if (cruft.indexOf(entry) !== -1) {
        --i
        next()
        continue
      }

      stat(resolve(root, entry), function (error, stats) {
        if (error) return cb(error)

        if (stats.isDirectory()) {
          readArtist(root, entry, function (error, artist) {
            if (error) return cb(error)

            --i
            artists.push(artist)

            next()
          })
        }
        else {
          --i
          next()
        }
      })
    }

    function next () {
      if (i === 0) cb(null, artists, artists.reduce((t, a) => t.concat(a.albums), []))
    }
  })
}

function readArtist (root, directory, cb_) {
  const cb = once(cb_)
  const artistPath = resolve(root, directory)
  readdir(artistPath, function (error, entries) {
    if (error) return cb(error)

    const albums = []

    let i = entries.length
    for (let entry of entries) {
      if (cruft.indexOf(entry) !== -1) {
        --i
        next()
        continue
      }

      const currentPath = resolve(artistPath, entry)
      stat(currentPath, function (error, stats) {
        if (error) return cb(error)

        if (stats.isDirectory()) {
          readAlbum(root, directory, entry, function (error, album) {
            if (error) return cb(error)

            --i
            albums.push(album)
            next()
          })
        }
        else if (stats.isFile()) {
          --i
          const ext = extname(entry)
          const base = resolve(artistPath, basename(entry, ext))
          switch (ext) {
            case ".flac":
            case ".mp3":
              albums.push(new Singletrack(
                entry,
                directory,
                currentPath,
                stats
              ))
              break
            case ".cue":
              cues.set(base, currentPath)
              break
            case ".log":
              // nothing to do with these
              break
            default:
              console.log("not sure what to do", entry)
          }
          next()
        }
        else {
          i--
          console.log("rando in artist directory:", directory, entry)
        }
      })
    }

    function next () {
      if (i > 0) return

      for (let a of albums) {
        const p = a.path
        const ext = extname(p)
        const base = resolve(dirname(p), basename(p, ext))
        if (cues.get(base)) a.cuesheet = cues.get(base)
      }
      cb(null, new Artist(directory, albums))
    }
  })
}

function readAlbum (root, artist, album, cb_) {
  const cb = once(cb_)

  const albumPath = resolve(root, artist, album)
  readdir(albumPath, function (error, entries) {
    if (error) return cb(error)

    const tracks = []
    const covers = []

    let i = entries.length
    for (let entry of entries) {
      if (cruft.indexOf(entry) !== -1) {
        i--
        next()
        continue
      }

      stat(resolve(albumPath, entry), function (error, stats) {
        if (stats.isDirectory()) {
          i--
          console.log("witaf. what is a directory doing here?", entry)
          next()
        }
        else if (stats.isFile()) {
          i--
          switch (extname(entry)) {
            case ".flac":
            case ".mp3":
              tracks.push(new Track(
                artist,
                album,
                entry,
                stats
              ))
              break
            case ".jpg":
            case ".pdf":
            case ".png":
              covers.push(new Cover(
                resolve(albumPath, entry),
                stats
              ))
              break
            default:
              console.log("I dunno, boss", entry)
          }
          next()
        }
        else {
          i--
          console.log("what", entry)
          next()
        }
      })
    }

    function next () {
      if (i > 0) return

      const a = new Multitrack(album, artist, albumPath, tracks)
      if (covers.length) a.pictures = covers

      cb(null, a)
    }
  })
}

readRoot(roots[0], function (error, artists, albums) {
  if (error) throw error

  for (let a of albums) { console.log("%s - %s [%s]", a.artist, a.name, a.getSize(1024 * 1024)) }
  for (let a of artists) { console.log("%s [%s]", a.name, a.getSize(1024 * 1024)) }
})
<|endoftext|>


<commit_before>// Draw parameters
var pc_SIZE = 16;

// Legend:
//  #: wall
//   : no cheese
//  .: cheese
//  o: big cheese
//  s: starting point
//  g: ghost starting point
//  _: forbidden for player
var pc_grid_template = [
	"############################",
	"#............##............#",
	"#.####.#####.##.#####.####.#",
	"#o####.#####.##.#####.####o#",
	"#.####.#####.##.#####.####.#",
	"#..........................#",
	"#.####.##.########.##.####.#",
	"#.####.##.########.##.####.#",
	"#......##....##....##......#",
	"######.#####.##.#####.######",
	"######.#####.##.#####.######",
	"######.##..........##.######",
	"######.##.###__###.##.######",
	"######.##.#gggggg#.##.######",
	"      ....#gggggg#....      ",
	"######.##.#gggggg#.##.######",
	"######.##.########.##.######",
	"######.##..........##.######",
	"######.##.########.##.######",
	"######.##.########.##.######",
	"#............##............#",
	"#.####.#####.##.#####.####.#",
	"#o####.#####.##.#####.####o#",
	"#...##.......s........##...#",
	"###.##.##.########.##.##.###",
	"###.##.##.########.##.##.###",
	"#......##....##....##......#",
	"#.##########.##.##########.#",
	"#.##########.##.##########.#",
	"#..........................#",
	"############################",
];
var pc_grid = [];

var pc_LEFT = 0;
var pc_UP = 1;
var pc_RIGHT = 2;
var pc_DOWN = 3;
var pc_FPS = 20;
var pc_FRAMES_PER_CELL = 5;

/**
 * User position
 */

var pc_pacman_x = -1;
var pc_pacman_y = -1;
var pc_pacman_direction = pc_LEFT;
var pc_pacman_next_direction = pc_LEFT;
var pc_current_frame = -1;

/**
 * Initialize the game
 */

function initGame() {
	// Already launched?
	if (pc_pacman_x != -1 || pc_pacman_y != -1 || pc_current_frame != -1)
		return;
	pc_pacman_direction = pc_LEFT;
	pc_pacman_next_direction = pc_LEFT;
	pc_current_frame = 0;

	// Copy the grid into local grid
	pc_grid = pc_grid_template.slice();

	// Find the starting point
	var height = pc_grid.length;
	var width = pc_grid[0].length;
	for (i=0 ; i!=width ; i++) {
		for (j=0 ; j!=height ; j++) {
			if (pc_grid[j][i] == 's') {
				pc_pacman_x = i * pc_FRAMES_PER_CELL;
				pc_pacman_y = j * pc_FRAMES_PER_CELL;
			}
		}
	}

	// Resize canvas
	var canvas = document.getElementById('myCanvas');
	if (! canvas.getContext)
		return;
	var ctx = canvas.getContext('2d');
	var height = pc_grid.length;
	var width = pc_grid[0].length;
	canvas.width = width*pc_SIZE +10;
	canvas.height = height*pc_SIZE +10;

	// Launch the game
	iterateGame();
}

/**
 * Iterate inside the game
 */

function iterateGame() {
	var canvas = document.getElementById('myCanvas');
	if (! canvas.getContext)
		return;
	var ctx = canvas.getContext('2d');
	var height = pc_grid.length;
	var width = pc_grid[0].length;

	// Change of direction
	// Opposite direction
	if (pc_pacman_direction == (pc_pacman_next_direction+2)%4)
		pc_pacman_direction = pc_pacman_next_direction;
	// Move ended? and possible direction
	else if (pc_pacman_x%pc_FRAMES_PER_CELL == 0 && pc_pacman_y%pc_FRAMES_PER_CELL == 0) {
		// Check if possible direction
		var cell_x = pc_pacman_x/pc_FRAMES_PER_CELL;
		var cell_y = pc_pacman_y/pc_FRAMES_PER_CELL;

		if (pc_pacman_next_direction == pc_LEFT) {
		       if ((cell_x > 0 && !isForbiddenForPacMan(pc_grid[cell_y][cell_x-1]) || (cell_x == 0 && !isForbiddenForPacMan(pc_grid[cell_y][width-1]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else if (pc_pacman_next_direction == pc_UP) {
		       if ((cell_y > 0 && !isForbiddenForPacMan(pc_grid[cell_y-1][cell_x]) || (cell_y == 0 && !isForbiddenForPacMan(pc_grid[height-1][cell_x]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else if (pc_pacman_next_direction == pc_RIGHT) {
		       if ((cell_x < width-1 && !isForbiddenForPacMan(pc_grid[cell_y][cell_x+1]) || (cell_x == width-1 && !isForbiddenForPacMan(pc_grid[cell_y][0]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else {
		       if ((cell_y < height-1 && !isForbiddenForPacMan(pc_grid[cell_y+1][cell_x]) || (cell_y == height-1 && !isForbiddenForPacMan(pc_grid[0][cell_x]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		}
	}

	// Move characters
	if (pc_pacman_direction == pc_LEFT) {
		pc_pacman_x--;
		// out of the grid
		if (pc_pacman_x < 0)
			pc_pacman_x = (width -1) * pc_FRAMES_PER_CELL;
		// into a wall
		else if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][Math.floor(1.*pc_pacman_x/pc_FRAMES_PER_CELL)]))
			pc_pacman_x++;
	} else if (pc_pacman_direction == pc_UP) {
		pc_pacman_y--;
		// out of the grid
		if (pc_pacman_y < 0)
			pc_pacman_y = (height -1) * pc_FRAMES_PER_CELL;
		// into a wall
		else if (isForbiddenForPacMan(pc_grid[Math.floor(1.*pc_pacman_y/pc_FRAMES_PER_CELL)][pc_pacman_x/pc_FRAMES_PER_CELL]))
			pc_pacman_y++;
	} else if (pc_pacman_direction == pc_RIGHT) {
		pc_pacman_x++;
		// out of the grid
		if (pc_pacman_x > (width -1) * pc_FRAMES_PER_CELL)
			pc_pacman_x = 0;
		// into a wall
		else if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][Math.ceil(1.*pc_pacman_x/pc_FRAMES_PER_CELL)]))
			pc_pacman_x--;
	} else {
		pc_pacman_y++;
		// out of the grid
		if (pc_pacman_y > (height -1) * pc_FRAMES_PER_CELL)
			pc_pacman_y = 0;
		// into a wall
		else if (isForbiddenForPacMan(pc_grid[Math.ceil(1.*pc_pacman_y/pc_FRAMES_PER_CELL)][pc_pacman_x/pc_FRAMES_PER_CELL]))
			pc_pacman_y--;
	}

	// Draw game
	drawEmptyGameBoard(canvas, ctx);
	drawPacMan(canvas, ctx);

	pc_current_frame++;
	setTimeout(iterateGame, 1000/pc_FPS);
}

/**
 * Is forbidden for PacMan
 */

function isForbiddenForPacMan(cell_type) {
	return cell_type == "#" || cell_type == "g" || cell_type == "_";
}

/**
 * Draw an empty game board
 */

function drawEmptyGameBoard(canvas, ctx) {
	/**
	 * Draw the Game Board based on pc_grid
	 */

	// Retrieve grid dimensions
	var height = pc_grid.length;
	var width = pc_grid[0].length;

	// Draw Game Board
	ctx.beginPath();
	ctx.fillStyle = "white";
	ctx.fillRect(0, 0, width*pc_SIZE +10, height*pc_SIZE +10);
	ctx.fill();

	ctx.beginPath();
	ctx.lineWidth = 3;
	ctx.strokeStyle = "black";
	ctx.moveTo(2, 2);
	ctx.lineTo(2, height*pc_SIZE +8);
	ctx.lineTo(width*pc_SIZE +8, height*pc_SIZE +8);
	ctx.lineTo(width*pc_SIZE +8, 2);
	ctx.closePath();
	ctx.stroke();

	for (i=0 ; i!=width ; i++) {
		for (j=0 ; j!=height ; j++) {
			if (pc_grid[j][i] == '#') {
				ctx.fillStyle = "#777777";
				ctx.fillRect(i*pc_SIZE +5, j*pc_SIZE +5, pc_SIZE, pc_SIZE);
			} else if (pc_grid[j][i] == '.') {
				ctx.beginPath();
				ctx.fillStyle = "#aaaa00";
				ctx.arc((i+.5)*pc_SIZE +5, (j+.5)*pc_SIZE +5, .2*pc_SIZE, 0, 2*Math.PI, false);
				ctx.fill();
			} else if (pc_grid[j][i] == 'o') {
				ctx.beginPath();
				ctx.fillStyle = "#aaaa00";
				ctx.arc((i+.5)*pc_SIZE +5, (j+.5)*pc_SIZE +5, .4*pc_SIZE, 0, 2*Math.PI, false);
				ctx.fill();
			}
		}
	}
}

/**
 * Draw the PacMan
 */

function drawPacMan(canvas, ctx) {
	var pacman_px_x = (1.*pc_pacman_x/pc_FRAMES_PER_CELL +.5)*pc_SIZE +5;
	var pacman_px_y = (1.*pc_pacman_y/pc_FRAMES_PER_CELL +.5)*pc_SIZE +5;
	var pacman_mouth = pc_current_frame%pc_FRAMES_PER_CELL +3;

	ctx.beginPath();
	ctx.fillStyle = "#777700";
	if (pc_pacman_direction == pc_LEFT)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI+Math.PI/pacman_mouth, Math.PI-Math.PI/pacman_mouth,false);
	else if (pc_pacman_direction == pc_UP)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, -Math.PI/2+Math.PI/pacman_mouth, -Math.PI/2-Math.PI/pacman_mouth,false);
	else if (pc_pacman_direction == pc_RIGHT)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI/pacman_mouth, -Math.PI/pacman_mouth,false);
	else
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI/2+Math.PI/pacman_mouth, Math.PI/2-Math.PI/pacman_mouth,false);
	ctx.lineTo(pacman_px_x, pacman_px_y);
	ctx.fill();
}
<commit_msg>BUG fixed: When changing from one side of the board to another starting with a wall<commit_after>// Draw parameters
var pc_SIZE = 16;

// Legend:
//  #: wall
//   : no cheese
//  .: cheese
//  o: big cheese
//  s: starting point
//  g: ghost starting point
//  _: forbidden for player
var pc_grid_template = [
	"############################",
	"#............##............#",
	"#.####.#####.##.#####.####.#",
	"#o####.#####.##.#####.####o#",
	"#.####.#####.##.#####.####.#",
	"#..........................#",
	"#.####.##.########.##.####.#",
	"#.####.##.########.##.####.#",
	"#......##....##....##......#",
	"######.#####.##.#####.######",
	"######.#####.##.#####.######",
	"######.##..........##.######",
	"######.##.###__###.##.######",
	"######.##.#gggggg#.##.######",
	"      ....#gggggg#....      ",
	"######.##.#gggggg#.##.######",
	"######.##.########.##.######",
	"######.##..........##.######",
	"######.##.########.##.######",
	"######.##.########.##.######",
	"#............##............#",
	"#.####.#####.##.#####.####.#",
	"#o####.#####.##.#####.####o#",
	"#...##.......s........##...#",
	"###.##.##.########.##.##.###",
	"###.##.##.########.##.##.###",
	"#......##....##....##......#",
	"#.##########.##.##########.#",
	"#.##########.##.##########.#",
	"#..........................#",
	"############################",
];
var pc_grid = [];

var pc_LEFT = 0;
var pc_UP = 1;
var pc_RIGHT = 2;
var pc_DOWN = 3;
var pc_FPS = 20;
var pc_FRAMES_PER_CELL = 5;

/**
 * User position
 */

var pc_pacman_x = -1;
var pc_pacman_y = -1;
var pc_pacman_direction = pc_LEFT;
var pc_pacman_next_direction = pc_LEFT;
var pc_current_frame = -1;

/**
 * Initialize the game
 */

function initGame() {
	// Already launched?
	if (pc_pacman_x != -1 || pc_pacman_y != -1 || pc_current_frame != -1)
		return;
	pc_pacman_direction = pc_LEFT;
	pc_pacman_next_direction = pc_LEFT;
	pc_current_frame = 0;

	// Copy the grid into local grid
	pc_grid = pc_grid_template.slice();

	// Find the starting point
	var height = pc_grid.length;
	var width = pc_grid[0].length;
	for (i=0 ; i!=width ; i++) {
		for (j=0 ; j!=height ; j++) {
			if (pc_grid[j][i] == 's') {
				pc_pacman_x = i * pc_FRAMES_PER_CELL;
				pc_pacman_y = j * pc_FRAMES_PER_CELL;
			}
		}
	}

	// Resize canvas
	var canvas = document.getElementById('myCanvas');
	if (! canvas.getContext)
		return;
	var ctx = canvas.getContext('2d');
	var height = pc_grid.length;
	var width = pc_grid[0].length;
	canvas.width = width*pc_SIZE +10;
	canvas.height = height*pc_SIZE +10;

	// Launch the game
	iterateGame();
}

/**
 * Iterate inside the game
 */

function iterateGame() {
	var canvas = document.getElementById('myCanvas');
	if (! canvas.getContext)
		return;
	var ctx = canvas.getContext('2d');
	var height = pc_grid.length;
	var width = pc_grid[0].length;

	// Change of direction
	// Opposite direction
	if (pc_pacman_direction == (pc_pacman_next_direction+2)%4)
		pc_pacman_direction = pc_pacman_next_direction;
	// Move ended? and possible direction
	else if (pc_pacman_x%pc_FRAMES_PER_CELL == 0 && pc_pacman_y%pc_FRAMES_PER_CELL == 0) {
		// Check if possible direction
		var cell_x = pc_pacman_x/pc_FRAMES_PER_CELL;
		var cell_y = pc_pacman_y/pc_FRAMES_PER_CELL;

		if (pc_pacman_next_direction == pc_LEFT) {
		       if ((cell_x > 0 && !isForbiddenForPacMan(pc_grid[cell_y][cell_x-1]) || (cell_x == 0 && !isForbiddenForPacMan(pc_grid[cell_y][width-1]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else if (pc_pacman_next_direction == pc_UP) {
		       if ((cell_y > 0 && !isForbiddenForPacMan(pc_grid[cell_y-1][cell_x]) || (cell_y == 0 && !isForbiddenForPacMan(pc_grid[height-1][cell_x]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else if (pc_pacman_next_direction == pc_RIGHT) {
		       if ((cell_x < width-1 && !isForbiddenForPacMan(pc_grid[cell_y][cell_x+1]) || (cell_x == width-1 && !isForbiddenForPacMan(pc_grid[cell_y][0]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		} else {
		       if ((cell_y < height-1 && !isForbiddenForPacMan(pc_grid[cell_y+1][cell_x]) || (cell_y == height-1 && !isForbiddenForPacMan(pc_grid[0][cell_x]))))
			       pc_pacman_direction = pc_pacman_next_direction;
		}
	}

	// Move characters
	if (pc_pacman_direction == pc_LEFT) {
		pc_pacman_x--;
		// out of the grid
		if (pc_pacman_x < 0) {
			pc_pacman_x = (width -1) * pc_FRAMES_PER_CELL;
			if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][pc_pacman_x/pc_FRAMES_PER_CELL]))
				pc_pacman_x = 0;
		// into a wall
		} else if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][Math.floor(1.*pc_pacman_x/pc_FRAMES_PER_CELL)]))
			pc_pacman_x++;
	} else if (pc_pacman_direction == pc_UP) {
		pc_pacman_y--;
		// out of the grid
		if (pc_pacman_y < 0) {
			pc_pacman_y = (height -1) * pc_FRAMES_PER_CELL;
			if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][pc_pacman_x/pc_FRAMES_PER_CELL]))
				pc_pacman_y = 0;
		// into a wall
		} else if (isForbiddenForPacMan(pc_grid[Math.floor(1.*pc_pacman_y/pc_FRAMES_PER_CELL)][pc_pacman_x/pc_FRAMES_PER_CELL]))
			pc_pacman_y++;
	} else if (pc_pacman_direction == pc_RIGHT) {
		pc_pacman_x++;
		// out of the grid
		if (pc_pacman_x > (width -1) * pc_FRAMES_PER_CELL) {
			pc_pacman_x = 0;
			if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][pc_pacman_x/pc_FRAMES_PER_CELL]))
				pc_pacman_x = (width -1) * pc_FRAMES_PER_CELL;
		// into a wall
		} else if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][Math.ceil(1.*pc_pacman_x/pc_FRAMES_PER_CELL)]))
			pc_pacman_x--;
	} else {
		pc_pacman_y++;
		// out of the grid
		if (pc_pacman_y > (height -1) * pc_FRAMES_PER_CELL) {
			pc_pacman_y = 0;
			if (isForbiddenForPacMan(pc_grid[pc_pacman_y/pc_FRAMES_PER_CELL][pc_pacman_x/pc_FRAMES_PER_CELL]))
				pc_pacman_y = (height -1) * pc_FRAMES_PER_CELL;
		// into a wall
		} else if (isForbiddenForPacMan(pc_grid[Math.ceil(1.*pc_pacman_y/pc_FRAMES_PER_CELL)][pc_pacman_x/pc_FRAMES_PER_CELL]))
			pc_pacman_y--;
	}

	// Draw game
	drawEmptyGameBoard(canvas, ctx);
	drawPacMan(canvas, ctx);

	pc_current_frame++;
	setTimeout(iterateGame, 1000/pc_FPS);
}

/**
 * Is forbidden for PacMan
 */

function isForbiddenForPacMan(cell_type) {
	return cell_type == "#" || cell_type == "g" || cell_type == "_";
}

/**
 * Draw an empty game board
 */

function drawEmptyGameBoard(canvas, ctx) {
	/**
	 * Draw the Game Board based on pc_grid
	 */

	// Retrieve grid dimensions
	var height = pc_grid.length;
	var width = pc_grid[0].length;

	// Draw Game Board
	ctx.beginPath();
	ctx.fillStyle = "white";
	ctx.fillRect(0, 0, width*pc_SIZE +10, height*pc_SIZE +10);
	ctx.fill();

	ctx.beginPath();
	ctx.lineWidth = 3;
	ctx.strokeStyle = "black";
	ctx.moveTo(2, 2);
	ctx.lineTo(2, height*pc_SIZE +8);
	ctx.lineTo(width*pc_SIZE +8, height*pc_SIZE +8);
	ctx.lineTo(width*pc_SIZE +8, 2);
	ctx.closePath();
	ctx.stroke();

	for (i=0 ; i!=width ; i++) {
		for (j=0 ; j!=height ; j++) {
			if (pc_grid[j][i] == '#') {
				ctx.fillStyle = "#777777";
				ctx.fillRect(i*pc_SIZE +5, j*pc_SIZE +5, pc_SIZE, pc_SIZE);
			} else if (pc_grid[j][i] == '.') {
				ctx.beginPath();
				ctx.fillStyle = "#aaaa00";
				ctx.arc((i+.5)*pc_SIZE +5, (j+.5)*pc_SIZE +5, .2*pc_SIZE, 0, 2*Math.PI, false);
				ctx.fill();
			} else if (pc_grid[j][i] == 'o') {
				ctx.beginPath();
				ctx.fillStyle = "#aaaa00";
				ctx.arc((i+.5)*pc_SIZE +5, (j+.5)*pc_SIZE +5, .4*pc_SIZE, 0, 2*Math.PI, false);
				ctx.fill();
			}
		}
	}
}

/**
 * Draw the PacMan
 */

function drawPacMan(canvas, ctx) {
	var pacman_px_x = (1.*pc_pacman_x/pc_FRAMES_PER_CELL +.5)*pc_SIZE +5;
	var pacman_px_y = (1.*pc_pacman_y/pc_FRAMES_PER_CELL +.5)*pc_SIZE +5;
	var pacman_mouth = pc_current_frame%pc_FRAMES_PER_CELL +3;

	ctx.beginPath();
	ctx.fillStyle = "#777700";
	if (pc_pacman_direction == pc_LEFT)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI+Math.PI/pacman_mouth, Math.PI-Math.PI/pacman_mouth,false);
	else if (pc_pacman_direction == pc_UP)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, -Math.PI/2+Math.PI/pacman_mouth, -Math.PI/2-Math.PI/pacman_mouth,false);
	else if (pc_pacman_direction == pc_RIGHT)
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI/pacman_mouth, -Math.PI/pacman_mouth,false);
	else
		ctx.arc(pacman_px_x, pacman_px_y, .45*pc_SIZE, Math.PI/2+Math.PI/pacman_mouth, Math.PI/2-Math.PI/pacman_mouth,false);
	ctx.lineTo(pacman_px_x, pacman_px_y);
	ctx.fill();
}
<|endoftext|>


<commit_before>define(['jquery', 'backbone', 'underscore'], function ($, Backbone, _) {
    return Backbone.View.extend({

        template:_.template($('#tiddler-template').html()),

        render:function () {
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        }

    });
});<commit_msg>Space between render signature and function keyword.<commit_after>define(['jquery', 'backbone', 'underscore'], function ($, Backbone, _) {
    return Backbone.View.extend({

        template:_.template($('#tiddler-template').html()),

        render: function () {
            $(this.el).html(this.template(this.model.toJSON()));
            return this;
        }

    });
});<|endoftext|>


<commit_before>$(function() {

  $("form").on('submit', function(e) {
    var $fadeElement = $(".fade-on-submit");
    if (!$fadeElement) return;

    e.preventDefault();
    $fadeElement.fadeOut(400, function() {
      var $hidden = $(".hidden");
      $hidden.fadeIn(400);
      $hidden.removeClass("hidden");
    });
  });
});<commit_msg>Scoped submit event to forms with fade-on-submit class.<commit_after>$(function() {

  $("form.fade-on-submit").on('submit', function(e) {
    var $fadeElement = $(".fade-on-submit");
    if (!$fadeElement) return;

    e.preventDefault();
    $fadeElement.fadeOut(400, function() {
      var $hidden = $(".hidden");
      $hidden.fadeIn(400);
      $hidden.removeClass("hidden");
    });
  });
});<|endoftext|>