<commit_before>/*
 * Bump mapping demo
 *
 * Written by Aleksi Asikainen 2013.
 *
 */

/**
 * @param {string} targetCanvasID
 * @param {CanvasTexture} texture
 * @param {CanvasTexture} heightMapTexture
 * @returns {Bumper}
 */

function Bumper( targetCanvasID, texture, heightMapTexture )
{
	this.targetCanvasID			= targetCanvasID;
	this.heightMapTexture		= heightMapTexture;
	this.texture				= texture;

	this.targetCanvas			= Helper.getElement( this.targetCanvasID );

	this.lightPosition			= new Vector3D();
	this.drawing				= false;
	this.precalculated			= false;
	this.precalculatedNormals	= [];
	this.embossDepth			= 3;

	// Precalculate normals once height map has been loaded:
	var me = this;

	this.heightMapTexture.onload = function()
		{
			me.precalculateNormals();
		};
}

Bumper.prototype = {

	/**
	 * @param {float} pointHeight Height at X, Y
	 * @param {float} pointHeightRight Height at X + 1, Y
	 * @param {float} pointHeightAbove Height at X, Y - 1
	 * @return {Vector3D} Bump map normal
	 */

	calculateNormal : function( pointHeight, pointHeightRight, pointHeightAbove )
	{
		var phphaDifference = pointHeight - pointHeightAbove;
		var phphrDifference = pointHeight - pointHeightRight;

		var divisor = Math.sqrt(
							( phphaDifference * phphaDifference )
							+
							( phphrDifference * phphrDifference )
							+
							this.embossDepth
						);

		/**
		 * Note: Have taken out z / divisor here, because it softens the image
		 * image too much for my taste.
		 */

		return new Vector3D( phphaDifference / divisor, phphrDifference / divisor, this.embossDepth /* / divisor */ );
	},

	/**
	 * Calculates a normal for each pixel in the height map
	 */

	precalculateNormals : function()
	{
		var width		= this.heightMapTexture.getWidth();
		var height		= this.heightMapTexture.getHeight();
		var abovePtr	= 0;
		var ptr			= width * 4; // ignore first line
		var singlePtr	= width;
		var widthMinus	= width - 1;
		var pixels		= this.heightMapTexture.getPixels();
		var data		= pixels.data;

		this.precalculatedNormals = new Array( width * height );

		for( var y = 1; y < height; y++ )
		{
			for( var x = 0; x < widthMinus; x++ )
			{
				var bumpNormal = this.calculateNormal(
						data[ ptr ],
						data[ ptr + 4 ],
						data[ abovePtr ]
					);

				this.precalculatedNormals[ singlePtr ] = bumpNormal.normalize();

				abovePtr	+= 4;
				ptr			+= 4;

				singlePtr++;
			}

			// Take in account width - 1
			abovePtr	+= 4;
			ptr			+= 4;

			singlePtr++;
		}

		this.precalculated = true;
	},

	draw : function()
	{
		if( this.isLoaded() !== true )
		{
			return;
		}

		if( this.hasPrecalculated() !== true )
		{
			this.precalculateNormals();
		}

		this.drawing	= true;

		var width		= this.heightMapTexture.getWidth();
		var height		= this.heightMapTexture.getHeight();
		var ptr			= width * 4; // ignore top line
		var singlePtr	= width;
		var widthMinus	= width - 1;

		var texturePixels	= this.texture.getPixels();
		var textureData		= texturePixels.data;

		var precalc			= this.precalculatedNormals;
		var realLightPos	= new Vector3D();
		var lightPos		= this.lightPosition;
		var lightPosZDiv2	= lightPos.z / 2;

		for( var y = 1; y < height; y++ )
		{
			for( var x = 0; x < widthMinus; x++ )
			{
				realLightPos.set( -( lightPos.y - y ), ( lightPos.x - x ) , lightPosZDiv2 );

				var bumpDot		= realLightPos.dot( precalc[ singlePtr ] );
				var distMul		= bumpDot / lightPos.distance( x, y, 0 );

				var ptrpp		= ptr + 1;
				var ptrp2		= ptr + 2;

				textureData[ ptr ]		= textureData[ ptr ] * distMul;
				textureData[ ptrpp ]	= textureData[ ptrpp ] * distMul;
				textureData[ ptrp2 ]	= textureData[ ptrp2 ] * distMul;

				ptr += 4;
				singlePtr++;
			}

			// take in account width - 1
			ptr += 4;
			singlePtr++;
		}

		this.targetCanvas.getContext( '2d' ).putImageData( texturePixels, 0, 0 );

		this.drawing = false;
	},

	/**
	 * @param {float} x
	 * @param {float} y
	 * @param {float} z
	 */

	setLightPos : function( x, y, z )
	{
		this.lightPosition.x = x;
		this.lightPosition.y = y;
		this.lightPosition.z = z;
	},

	/**
	 * @param {float} depth
	 */

	setEmbossDepth : function( depth )
	{
		this.embossDepth = depth;

		this.precalculateNormals();
	},

	/**
	 * @returns {Boolean}
	 */

	isDrawing : function()
	{
		return this.drawing;
	},

	/**
	 * @returns {Boolean}
	 */

	isLoaded : function()
	{
		if( ( this.heightMapTexture.loaded === true ) && ( this.texture.loaded === true ) )
		{
			return true;
		}

		return false;
	},

	/**
	 * @returns {Boolean}
	 */

	hasPrecalculated : function()
	{
		return this.precalculated;
	}

};

<commit_msg>Fixed what got broken with refactoring of Vector3D class<commit_after>/*
 * Bump mapping demo
 *
 * Written by Aleksi Asikainen 2013.
 *
 */

/**
 * @param {string} targetCanvasID
 * @param {CanvasTexture} texture
 * @param {CanvasTexture} heightMapTexture
 * @returns {Bumper}
 */

function Bumper( targetCanvasID, texture, heightMapTexture )
{
	this.targetCanvasID			= targetCanvasID;
	this.heightMapTexture		= heightMapTexture;
	this.texture				= texture;

	this.targetCanvas			= Helper.getElement( this.targetCanvasID );

	this.lightPosition			= new Vector3D();
	this.drawing				= false;
	this.precalculated			= false;
	this.precalculatedNormals	= [];
	this.embossDepth			= 3;

	// Precalculate normals once height map has been loaded:
	var me = this;

	this.heightMapTexture.onload = function()
		{
			me.precalculateNormals();
		};
}

Bumper.prototype = {

	/**
	 * @param {float} pointHeight Height at X, Y
	 * @param {float} pointHeightRight Height at X + 1, Y
	 * @param {float} pointHeightAbove Height at X, Y - 1
	 * @return {Vector3D} Bump map normal
	 */

	calculateNormal : function( pointHeight, pointHeightRight, pointHeightAbove )
	{
		var phphaDifference = pointHeight - pointHeightAbove;
		var phphrDifference = pointHeight - pointHeightRight;

		var divisor = Math.sqrt(
							( phphaDifference * phphaDifference )
							+
							( phphrDifference * phphrDifference )
							+
							this.embossDepth
						);

		/**
		 * Note: Have taken out z / divisor here, because it softens the image
		 * image too much for my taste.
		 */

		return new Vector3D( phphaDifference / divisor, phphrDifference / divisor, this.embossDepth /* / divisor */ );
	},

	/**
	 * Calculates a normal for each pixel in the height map
	 */

	precalculateNormals : function()
	{
		var width		= this.heightMapTexture.getWidth();
		var height		= this.heightMapTexture.getHeight();
		var abovePtr	= 0;
		var ptr			= width * 4; // ignore first line
		var singlePtr	= width;
		var widthMinus	= width - 1;
		var pixels		= this.heightMapTexture.getPixels();
		var data		= pixels.data;

		this.precalculatedNormals = new Array( width * height );

		for( var y = 1; y < height; y++ )
		{
			for( var x = 0; x < widthMinus; x++ )
			{
				var bumpNormal = this.calculateNormal(
						data[ ptr ],
						data[ ptr + 4 ],
						data[ abovePtr ]
					);

				bumpNormal.normalize();

				this.precalculatedNormals[ singlePtr ] = bumpNormal;

				abovePtr	+= 4;
				ptr			+= 4;

				singlePtr++;
			}

			// Take in account width - 1
			abovePtr	+= 4;
			ptr			+= 4;

			singlePtr++;
		}

		this.precalculated = true;
	},

	draw : function()
	{
		if( this.isLoaded() !== true )
		{
			return;
		}

		if( this.hasPrecalculated() !== true )
		{
			this.precalculateNormals();
		}

		this.drawing	= true;

		var width		= this.heightMapTexture.getWidth();
		var height		= this.heightMapTexture.getHeight();
		var ptr			= width * 4; // ignore top line
		var singlePtr	= width;
		var widthMinus	= width - 1;

		var texturePixels	= this.texture.getPixels();
		var textureData		= texturePixels.data;

		var precalc			= this.precalculatedNormals;
		var realLightPos	= new Vector3D();
		var lightPos		= this.lightPosition;
		var lightPosZDiv2	= lightPos.z / 2;

		for( var y = 1; y < height; y++ )
		{
			for( var x = 0; x < widthMinus; x++ )
			{
				realLightPos.set( -( lightPos.y - y ), ( lightPos.x - x ) , lightPosZDiv2 );

				var bumpDot		= realLightPos.dot( precalc[ singlePtr ] );
				var distMul		= bumpDot / lightPos.distance( x, y, 0 );

				var ptrpp		= ptr + 1;
				var ptrp2		= ptr + 2;

				textureData[ ptr ]		= textureData[ ptr ] * distMul;
				textureData[ ptrpp ]	= textureData[ ptrpp ] * distMul;
				textureData[ ptrp2 ]	= textureData[ ptrp2 ] * distMul;

				ptr += 4;
				singlePtr++;
			}

			// take in account width - 1
			ptr += 4;
			singlePtr++;
		}

		this.targetCanvas.getContext( '2d' ).putImageData( texturePixels, 0, 0 );

		this.drawing = false;
	},

	/**
	 * @param {float} x
	 * @param {float} y
	 * @param {float} z
	 */

	setLightPos : function( x, y, z )
	{
		this.lightPosition.x = x;
		this.lightPosition.y = y;
		this.lightPosition.z = z;
	},

	/**
	 * @param {float} depth
	 */

	setEmbossDepth : function( depth )
	{
		this.embossDepth = depth;

		this.precalculateNormals();
	},

	/**
	 * @returns {Boolean}
	 */

	isDrawing : function()
	{
		return this.drawing;
	},

	/**
	 * @returns {Boolean}
	 */

	isLoaded : function()
	{
		if( ( this.heightMapTexture.loaded === true ) && ( this.texture.loaded === true ) )
		{
			return true;
		}

		return false;
	},

	/**
	 * @returns {Boolean}
	 */

	hasPrecalculated : function()
	{
		return this.precalculated;
	}

};

<|endoftext|>


<commit_before>/* global createUsers, databases, wait, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
/* eslint-env browser,jasmine */
'use strict'

var Y = require('../../yjs/src/SpecHelper.js')

var numberOfYArrayTests = 10
var repeatArrayTests = 2

for (let database of databases) {
  describe(`Array Type (DB: ${database})`, function () {
    var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll

    beforeEach(async(function * (done) {
      yield createUsers(this, 3, database)
      y1 = (yconfig1 = this.users[0]).share.root
      y2 = (yconfig2 = this.users[1]).share.root
      y3 = (yconfig3 = this.users[2]).share.root
      flushAll = Y.utils.globalRoom.flushAll
      yield wait(10)
      done()
    }))
    afterEach(async(function * (done) {
      yield compareAllUsers(this.users)
      done()
    }))

    describe('Basic tests', function () {
      it('insert three elements, try re-get property', async(function * (done) {
        var array = yield y1.set('Array', Y.Array)
        array.insert(0, [1, 2, 3])
        array = yield y1.get('Array') // re-get property
        expect(array.toArray()).toEqual([1, 2, 3])
        done()
      }))
      it('Basic insert in array (handle three conflicts)', async(function * (done) {
        yield y1.set('Array', Y.Array)
        yield flushAll()
        var l1 = yield y1.get('Array')
        l1.insert(0, [0])
        var l2 = yield y2.get('Array')
        l2.insert(0, [1])
        var l3 = yield y3.get('Array')
        l3.insert(0, [2])
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        done()
      }))
      it('Basic insert&delete in array (handle three conflicts)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        l1.insert(1, [0])
        l2 = yield y2.get('Array')
        l2.delete(0)
        l2.delete(1)
        l3 = yield y3.get('Array')
        l3.insert(1, [2])
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([0, 2, 'y'])
        done()
      }))
      it('Handles getOperations ascending ids bug in late sync', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y'])
        yield flushAll()
        yconfig3.disconnect()
        yconfig2.disconnect()
        yield wait()
        l2 = yield y2.get('Array')
        l2.insert(1, [2])
        l2.insert(1, [3])
        yield yconfig2.reconnect()
        yield yconfig3.reconnect()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Handles deletions in late sync', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y'])
        yield flushAll()
        yield yconfig2.disconnect()
        yield wait()
        l2 = yield y2.get('Array')
        l2.delete(1, 1)
        l1.delete(0, 2)
        yield yconfig2.reconnect()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Handles deletions in late sync (2)', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        yield flushAll()
        l2 = yield y2.get('Array')
        l1.insert(0, ['x', 'y'])
        l1.delete(0, 2)
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Basic insert. Then delete the whole array', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      it('Basic insert. Then delete the whole array (merge listeners on late sync)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig2.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield wait()
        yield yconfig2.reconnect()
        yield wait()
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      // TODO?
      /* it('Basic insert. Then delete the whole array (merge deleter on late sync)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig1.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield yconfig1.reconnect()
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      })) */
      it('throw insert & delete events', async(function * (done) {
        var array = yield this.users[0].share.root.set('array', Y.Array)
        var event
        array.observe(function (e) {
          event = e
        })
        array.insert(0, [0])
        expect(event).toEqual([{
          type: 'insert',
          object: array,
          index: 0,
          value: 0,
          length: 1
        }])
        array.delete(0)
        expect(event).toEqual([{
          type: 'delete',
          object: array,
          index: 0,
          length: 1
        }])
        yield wait(50)
        done()
      }))
      it('garbage collects', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig1.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield wait()
        yield yconfig1.reconnect()
        yield wait()
        l3 = yield y3.get('Array')
        yield flushAll()
        yield garbageCollectAllUsers(this.users)
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      it('debug right not existend in Insert.execute', async(function * (done) {
        yconfig1.db.requestTransaction(function * () {
          var ops = [{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'left':null,'right':null,'origin':null,'parent':['130',0],'parentSub':'somekey','struct':'Insert','content':512,'id':['133',0]},{'id':['130',2],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':1131},{'id':['130',3],'left':null,'right':['130',2],'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':4196},{'id':['131',3],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':5022}]//eslint-disable-line

          for (var o of ops) {
            yield* this.store.tryExecute.call(this, o)
          }
        })
        yield wait()
        yield yconfig3.disconnect()
        yield yconfig2.disconnect()
        yield flushAll()
        wait()
        yield yconfig3.reconnect()
        yield yconfig2.reconnect()
        yield wait()
        yield flushAll()
        done()
      }))
      it('debug right not existend in Insert.execute (2)', async(function * (done) {
        yconfig1.db.requestTransaction(function * () {
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 3784, 'id': ['154', 0]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 0], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 8217, 'id': ['154', 1]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 1], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 5036, 'id': ['154', 2]})
          yield* this.store.tryExecute.call(this, {'id': ['153', 2], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 417})
          yield* this.store.tryExecute.call(this, {'id': ['155', 0], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 2202})
          yield* this.garbageCollectOperation(['153', 2])
          yield* this.garbageCollectOperation(['154', 0])
          yield* this.garbageCollectOperation(['154', 1])
          yield* this.garbageCollectOperation(['154', 2])
          yield* this.garbageCollectOperation(['155', 0])
          yield* this.garbageCollectOperation(['156', 0])
          yield* this.garbageCollectOperation(['157', 0])
          yield* this.garbageCollectOperation(['157', 1])
          yield* this.store.tryExecute.call(this, {'id': ['153', 3], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 4372})
        })
        yield wait()
        yield yconfig3.disconnect()
        yield yconfig2.disconnect()
        yield flushAll()
        wait()
        yield yconfig3.reconnect()
        yield yconfig2.reconnect()
        yield wait()
        yield flushAll()
        done()
      }))
    })
    describeManyTimes(repeatArrayTests, `Random tests`, function () {
      var randomArrayTransactions = [
        function insert (array) {
          array.insert(getRandomNumber(array.toArray().length), [getRandomNumber()])
        },
        function _delete (array) {
          var length = array.toArray().length
          if (length > 0) {
            array.delete(getRandomNumber(length - 1))
          }
        }
      ]
      function compareArrayValues (arrays) {
        var firstArray
        for (var l of arrays) {
          var val = l.toArray()
          if (firstArray == null) {
            firstArray = val
          } else {
            expect(val).toEqual(firstArray)
          }
        }
      }
      beforeEach(async(function * (done) {
        yield this.users[0].share.root.set('Array', Y.Array)
        yield flushAll()

        var promises = []
        for (var u = 0; u < this.users.length; u++) {
          promises.push(this.users[u].share.root.get('Array'))
        }
        this.arrays = yield Promise.all(promises)
        done()
      }))
      it('arrays.length equals users.length', async(function * (done) {
        expect(this.arrays.length).toEqual(this.users.length)
        done()
      }))
      it(`succeed after ${numberOfYArrayTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
        for (var u of this.users) {
          u.connector.debug = true
        }
        yield applyRandomTransactionsAllRejoinNoGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
        yield flushAll()
        yield compareArrayValues(this.arrays)
        yield compareAllUsers(this.users)
        done()
      }))
      it(`succeed after ${numberOfYArrayTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
        for (var u of this.users) {
          u.connector.debug = true
        }
        yield applyRandomTransactionsWithGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
        yield flushAll()
        yield compareArrayValues(this.arrays)
        yield compareAllUsers(this.users)
        done()
      }))
    })
  })
}
<commit_msg>fixed tests<commit_after>/* global createUsers, databases, wait, compareAllUsers, getRandomNumber, applyRandomTransactionsAllRejoinNoGC, applyRandomTransactionsWithGC, async, garbageCollectAllUsers, describeManyTimes */
/* eslint-env browser,jasmine */
'use strict'

var Y = require('../../yjs/src/SpecHelper.js')

var numberOfYArrayTests = 10
var repeatArrayTests = 2

for (let database of databases) {
  describe(`Array Type (DB: ${database})`, function () {
    var y1, y2, y3, yconfig1, yconfig2, yconfig3, flushAll

    beforeEach(async(function * (done) {
      yield createUsers(this, 3, database)
      y1 = (yconfig1 = this.users[0]).share.root
      y2 = (yconfig2 = this.users[1]).share.root
      y3 = (yconfig3 = this.users[2]).share.root
      flushAll = Y.utils.globalRoom.flushAll
      yield wait(10)
      done()
    }))
    afterEach(async(function * (done) {
      yield compareAllUsers(this.users)
      done()
    }))

    describe('Basic tests', function () {
      it('insert three elements, try re-get property', async(function * (done) {
        var array = yield y1.set('Array', Y.Array)
        array.insert(0, [1, 2, 3])
        array = yield y1.get('Array') // re-get property
        expect(array.toArray()).toEqual([1, 2, 3])
        done()
      }))
      it('Basic insert in array (handle three conflicts)', async(function * (done) {
        yield y1.set('Array', Y.Array)
        yield flushAll()
        var l1 = yield y1.get('Array')
        l1.insert(0, [0])
        var l2 = yield y2.get('Array')
        l2.insert(0, [1])
        var l3 = yield y3.get('Array')
        l3.insert(0, [2])
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        done()
      }))
      it('Basic insert&delete in array (handle three conflicts)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        l1.insert(1, [0])
        l2 = yield y2.get('Array')
        l2.delete(0)
        l2.delete(1)
        l3 = yield y3.get('Array')
        l3.insert(1, [2])
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([0, 2, 'y'])
        done()
      }))
      it('Handles getOperations ascending ids bug in late sync', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y'])
        yield flushAll()
        yconfig3.disconnect()
        yconfig2.disconnect()
        yield wait()
        l2 = yield y2.get('Array')
        l2.insert(1, [2])
        l2.insert(1, [3])
        yield yconfig2.reconnect()
        yield yconfig3.reconnect()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Handles deletions in late sync', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y'])
        yield flushAll()
        yield yconfig2.disconnect()
        yield wait()
        l2 = yield y2.get('Array')
        l2.delete(1, 1)
        l1.delete(0, 2)
        yield yconfig2.reconnect()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Handles deletions in late sync (2)', async(function * (done) {
        var l1, l2
        l1 = yield y1.set('Array', Y.Array)
        yield flushAll()
        l2 = yield y2.get('Array')
        l1.insert(0, ['x', 'y'])
        l1.delete(0, 2)
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        done()
      }))
      it('Basic insert. Then delete the whole array', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      it('Basic insert. Then delete the whole array (merge listeners on late sync)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig2.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield wait()
        yield yconfig2.reconnect()
        yield wait()
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      // TODO?
      /* it('Basic insert. Then delete the whole array (merge deleter on late sync)', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig1.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield yconfig1.reconnect()
        l3 = yield y3.get('Array')
        yield flushAll()
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      })) */
      it('throw insert & delete events', async(function * (done) {
        var array = yield this.users[0].share.root.set('array', Y.Array)
        var event
        array.observe(function (e) {
          event = e
        })
        array.insert(0, [0])
        expect(event).toEqual([{
          type: 'insert',
          object: array,
          index: 0,
          value: 0,
          length: 1
        }])
        array.delete(0)
        expect(event).toEqual([{
          type: 'delete',
          object: array,
          index: 0,
          length: 1,
          value: 0
        }])
        yield wait(50)
        done()
      }))
      it('garbage collects', async(function * (done) {
        var l1, l2, l3
        l1 = yield y1.set('Array', Y.Array)
        l1.insert(0, ['x', 'y', 'z'])
        yield flushAll()
        yconfig1.disconnect()
        l1.delete(0, 3)
        l2 = yield y2.get('Array')
        yield wait()
        yield yconfig1.reconnect()
        yield wait()
        l3 = yield y3.get('Array')
        yield flushAll()
        yield garbageCollectAllUsers(this.users)
        expect(l1.toArray()).toEqual(l2.toArray())
        expect(l2.toArray()).toEqual(l3.toArray())
        expect(l2.toArray()).toEqual([])
        done()
      }))
      it('debug right not existend in Insert.execute', async(function * (done) {
        yconfig1.db.requestTransaction(function * () {
          var ops = [{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'struct':'Map','type':'Map','id':['130',0],'map':{}},{'id':['130',1],'left':null,'right':null,'origin':null,'parent':['_',0],'struct':'Insert','parentSub':'Map','opContent':['130',0]},{'left':null,'right':null,'origin':null,'parent':['130',0],'parentSub':'somekey','struct':'Insert','content':512,'id':['133',0]},{'id':['130',2],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':1131},{'id':['130',3],'left':null,'right':['130',2],'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':4196},{'id':['131',3],'left':null,'right':null,'origin':null,'parent':['130',0],'struct':'Insert','parentSub':'somekey','content':5022}]//eslint-disable-line

          for (var o of ops) {
            yield* this.store.tryExecute.call(this, o)
          }
        })
        yield wait()
        yield yconfig3.disconnect()
        yield yconfig2.disconnect()
        yield flushAll()
        wait()
        yield yconfig3.reconnect()
        yield yconfig2.reconnect()
        yield wait()
        yield flushAll()
        done()
      }))
      it('debug right not existend in Insert.execute (2)', async(function * (done) {
        yconfig1.db.requestTransaction(function * () {
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'struct': 'Map', 'type': 'Map', 'id': ['153', 0], 'map': {}})
          yield* this.store.tryExecute.call(this, {'id': ['153', 1], 'left': null, 'right': null, 'origin': null, 'parent': ['_', 0], 'struct': 'Insert', 'parentSub': 'Map', 'opContent': ['153', 0]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 3784, 'id': ['154', 0]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 0], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 8217, 'id': ['154', 1]})
          yield* this.store.tryExecute.call(this, {'left': null, 'right': ['154', 1], 'origin': null, 'parent': ['153', 0], 'parentSub': 'somekey', 'struct': 'Insert', 'content': 5036, 'id': ['154', 2]})
          yield* this.store.tryExecute.call(this, {'id': ['153', 2], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 417})
          yield* this.store.tryExecute.call(this, {'id': ['155', 0], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 2202})
          yield* this.garbageCollectOperation(['153', 2])
          yield* this.garbageCollectOperation(['154', 0])
          yield* this.garbageCollectOperation(['154', 1])
          yield* this.garbageCollectOperation(['154', 2])
          yield* this.garbageCollectOperation(['155', 0])
          yield* this.garbageCollectOperation(['156', 0])
          yield* this.garbageCollectOperation(['157', 0])
          yield* this.garbageCollectOperation(['157', 1])
          yield* this.store.tryExecute.call(this, {'id': ['153', 3], 'left': null, 'right': null, 'origin': null, 'parent': ['153', 0], 'struct': 'Insert', 'parentSub': 'somekey', 'content': 4372})
        })
        yield wait()
        yield yconfig3.disconnect()
        yield yconfig2.disconnect()
        yield flushAll()
        wait()
        yield yconfig3.reconnect()
        yield yconfig2.reconnect()
        yield wait()
        yield flushAll()
        done()
      }))
    })
    describeManyTimes(repeatArrayTests, `Random tests`, function () {
      var randomArrayTransactions = [
        function insert (array) {
          array.insert(getRandomNumber(array.toArray().length), [getRandomNumber()])
        },
        function _delete (array) {
          var length = array.toArray().length
          if (length > 0) {
            array.delete(getRandomNumber(length - 1))
          }
        }
      ]
      function compareArrayValues (arrays) {
        var firstArray
        for (var l of arrays) {
          var val = l.toArray()
          if (firstArray == null) {
            firstArray = val
          } else {
            expect(val).toEqual(firstArray)
          }
        }
      }
      beforeEach(async(function * (done) {
        yield this.users[0].share.root.set('Array', Y.Array)
        yield flushAll()

        var promises = []
        for (var u = 0; u < this.users.length; u++) {
          promises.push(this.users[u].share.root.get('Array'))
        }
        this.arrays = yield Promise.all(promises)
        done()
      }))
      it('arrays.length equals users.length', async(function * (done) {
        expect(this.arrays.length).toEqual(this.users.length)
        done()
      }))
      it(`succeed after ${numberOfYArrayTests} actions, no GC, all users disconnecting/reconnecting`, async(function * (done) {
        for (var u of this.users) {
          u.connector.debug = true
        }
        yield applyRandomTransactionsAllRejoinNoGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
        yield flushAll()
        yield compareArrayValues(this.arrays)
        yield compareAllUsers(this.users)
        done()
      }))
      it(`succeed after ${numberOfYArrayTests} actions, GC, user[0] is not disconnecting`, async(function * (done) {
        for (var u of this.users) {
          u.connector.debug = true
        }
        yield applyRandomTransactionsWithGC(this.users, this.arrays, randomArrayTransactions, numberOfYArrayTests)
        yield flushAll()
        yield compareArrayValues(this.arrays)
        yield compareAllUsers(this.users)
        done()
      }))
    })
  })
}
<|endoftext|>


<commit_before>function LifeEngine() {

}

LifeEngine.prototype.isCellLiveNext = function(isLiveNow, neighborNumber) {
  if (isLiveNow == true){
    if(neighborNumber > 1 && neighborNumber < 4) {
      return true;
    } else {
      return false;
    };
  }
};

module.exports = LifeEngine;
<commit_msg>update life engine code<commit_after>function LifeEngine() {
}

LifeEngine.prototype.isCellLiveNext = function(isLiveNow, neighborNumber) {
  if (isLiveNow === true){
    if (neighborNumber > 1 && neighborNumber < 4) {
      return true;
    } else {
      return false;
    };
  } else {
    if (neighborNumber === 3) {
      return true;
    } else {
      return false;
    }
  }
};

module.exports = LifeEngine;
<|endoftext|>


<commit_before>import rp from 'request-promise'
import low from 'lowdb'
import stringify from 'json-stringify-pretty-compact'
import fileAsync from 'lowdb/lib/storages/file-async'
import wmean from 'weighted-mean'
import { season, year } from '../src/util'

const version = 'edge'
const base = `https://kitsu.io/api/${version}`
// Days since epoch
// const now = ~~(Date.now() / 1000 / 60 / 60 / 24)
const now = new Date().toISOString()

const q = {
  // 20 results per request
  limit: 'page[limit]=20',
  // Currently airing tv and min userCount of 10
  filter: 'filter[status]=current&filter[subtype]=tv',
  // Sort by highest rated then most users
  sort: 'sort=-averageRating,-userCount',
  fields: 'fields[anime]=slug,canonicalTitle,ratingFrequencies,userCount,favoritesCount,posterImage'
}

// Load season database
const db = low(`./data/${year()}-${season()}.json`, {
  storage: fileAsync,
  format: {
    serialize: data => stringify(data, { maxLength: 250 })
  }
})

// Set defaults if new season
db.defaults({ data: {} }).write()

// Array of all shows that have started airing. Airing shows will be
// removed, leaving only shows that have finished - which will be
// updated manually
const aired = Object.keys(db.get('data').value())

function display (count, processed, offset, { hasAired = false, removed = false } = {}) {
  try {
    if (!hasAired && offset + 20 > count) offset = count
    const progress = ((processed + offset) / count * 100)
    console.log(`${processed + offset} - ${(progress > 100 ? 100 : progress).toFixed(1)}% Complete${removed ? ' (deleted erroneous entry)' : ''}`)
  } catch (err) {
    console.error(err)
  }
}

async function get (path, { offset = 0, id = null, upcoming = false } = {}) {
  try {
    if (id) return JSON.parse(await rp(`${base}/${path}/${id}?${q.fields},endDate`))
    else if (upcoming) return JSON.parse(await rp(`${base}/${path}?page[offset]=${offset}&${q.limit}&${q.sort}&${q.fields}&filter[subtype]=tv&filter[season_year]=${year()}&filter[season]=${season()}`))
    else return JSON.parse(await rp(`${base}/${path}?page[offset]=${offset}&${q.limit}&${q.filter}&${q.sort}&${q.fields}`))
  } catch (err) {
    console.error(err)
  }
}

function calcRatings (frequency) {
  try {
    const ratings = Object.keys(frequency).map(key => [ key / 2, +frequency[key] ])
    return {
      mean: +wmean(ratings).toFixed(2) || 0, // Changing 0 (no ratings) to null is ideal
      usersRated: ratings.reduce((sum, x) => ~~x[1] + ~~(sum[1] ? sum[1] : sum), 0)
    }
  } catch (err) {
    console.error(err)
  }
}

async function set (id, attributes, { mean, usersRated }) {
  try {
    db.set(`data.${id}`, {
      id,
      updated: now,
      mean: [ mean ],
      slug: attributes.slug,
      usersRated: [ usersRated ],
      users: [ attributes.userCount ],
      title: attributes.canonicalTitle,
      poster: attributes.posterImage.medium,
      favorites: [ attributes.favoritesCount ]
    }).write()
  } catch (err) {
    console.error(err)
  }
}

async function update (id, attributes, { mean, usersRated }) {
  try {
    const latest = db.get(`data.${id}`).value()
    latest.updated = now
    latest.mean.push(mean)
    latest.slug = attributes.slug
    latest.usersRated.push(usersRated)
    latest.users.push(attributes.userCount)
    latest.title = attributes.canonicalTitle
    latest.poster = attributes.posterImage.medium
    latest.favorites.push(attributes.favoritesCount)
    db.set(`data.${id}`, latest).write()
  } catch (err) {
    console.error(err)
  }
}

async function check ({ id, attributes }) {
  try {
    const ratings = calcRatings(attributes.ratingFrequencies)
    if (!db.get(`data.${id}`).value()) await set(id, attributes, ratings)
    else await update(id, attributes, ratings)
  } catch (err) {
    console.error(err)
  }
}

async function remove ({ id }) {
  try {
    await db.unset(`data.${id}`).write()
  } catch (err) {
    console.error(err)
  }
}

async function getAiring (offset = 0) {
  try {
    const { data, meta, links } = await get('anime', { offset })
    for (let item of await data) {
      aired.splice(aired.indexOf(item.id), 1)
      await check(item)
    }
    await display(meta.count, data.length, offset)
    return links
  } catch (err) {
    console.error(err)
  }
}

// Updates shows that are airing this season, but have not yet aired
async function addUpcoming (offset = 0) {
  try {
    const { data, links } = await get('anime', {
      offset,
      upcoming: true
    })

    data.forEach(async anime => {
      const exists = db.get('data').find({ id: anime.id }).value()
      if (typeof exists === 'undefined') {
        await check(anime)
        console.log(`  Added ${anime.attributes.canonicalTitle}`)
      }
    })

    if (links.next) await addUpcoming(offset + 20)
  } catch (err) {
    console.error(err)
  }
}

// Updates shows that have finished - but aired during the season
// Additionally, also trims erroneous (old) shows from the data
function getAired () {
  try {
    aired.forEach(async id => {
      const { data } = await get('anime', { id })

      // Check if the show ended within this season
      // If not, it was an erroneous entry and shouldn't be in the season's data
      // at all - thus remove it entirely
      const ended = data.attributes.endDate
      const cutoff = new Date(now).getTime() - (3 * 30 * 24 * 60 * 60 * 1000)
      const endDate = new Date(ended === null ? new Date(now).getTime() + (24 * 60 * 60 * 100) : ended).getTime()
      if (endDate - cutoff > 0) await check(data)
      else await remove(data)

      console.log((endDate - cutoff > 0 ? 'Updated ' : 'Removed ') + data.attributes.canonicalTitle)
    })
  } catch (err) {
    console.error(err)
  }
}

(async function main (offset = 0) {
  try {
    const { next } = await getAiring(offset)
    if (next) await main(offset + 20)
    else {
      console.log('\nUpdating existing & upcoming anime:\n')
      await getAired()
      addUpcoming()
    }
  } catch (err) {
    console.error(err)
  }
})()
<commit_msg>chore: remove deprecated code<commit_after>import rp from 'request-promise'
import low from 'lowdb'
import stringify from 'json-stringify-pretty-compact'
import fileAsync from 'lowdb/lib/storages/file-async'
import wmean from 'weighted-mean'
import { season, year } from '../src/util'

const version = 'edge'
const base = `https://kitsu.io/api/${version}`
// Days since epoch
// const now = ~~(Date.now() / 1000 / 60 / 60 / 24)
const now = new Date().toISOString()

const q = {
  // 20 results per request
  limit: 'page[limit]=20',
  // Currently airing tv and min userCount of 10
  filter: 'filter[status]=current&filter[subtype]=tv',
  // Sort by highest rated then most users
  sort: 'sort=-averageRating,-userCount',
  fields: 'fields[anime]=slug,canonicalTitle,ratingFrequencies,userCount,favoritesCount,posterImage'
}

// Load season database
const db = low(`./data/${year()}-${season()}.json`, {
  storage: fileAsync,
  format: {
    serialize: data => stringify(data, { maxLength: 250 })
  }
})

// Set defaults if new season
db.defaults({ data: {} }).write()

// Array of all shows that have started airing. Airing shows will be
// removed, leaving only shows that have finished - which will be
// updated manually
const aired = Object.keys(db.get('data').value())

function display (count, processed, offset) {
  try {
    if (offset + 20 > count) offset = count
    const progress = ((processed + offset) / count * 100)
    console.log(`${processed + offset} - ${(progress > 100 ? 100 : progress).toFixed(1)}% Complete`)
  } catch (err) {
    console.error(err)
  }
}

async function get (path, { offset = 0, id = null, upcoming = false } = {}) {
  try {
    if (id) return JSON.parse(await rp(`${base}/${path}/${id}?${q.fields},endDate`))
    else if (upcoming) return JSON.parse(await rp(`${base}/${path}?page[offset]=${offset}&${q.limit}&${q.sort}&${q.fields}&filter[subtype]=tv&filter[season_year]=${year()}&filter[season]=${season()}`))
    else return JSON.parse(await rp(`${base}/${path}?page[offset]=${offset}&${q.limit}&${q.filter}&${q.sort}&${q.fields}`))
  } catch (err) {
    console.error(err)
  }
}

function calcRatings (frequency) {
  try {
    const ratings = Object.keys(frequency).map(key => [ key / 2, +frequency[key] ])
    return {
      mean: +wmean(ratings).toFixed(2) || 0, // Changing 0 (no ratings) to null is ideal
      usersRated: ratings.reduce((sum, x) => ~~x[1] + ~~(sum[1] ? sum[1] : sum), 0)
    }
  } catch (err) {
    console.error(err)
  }
}

async function set (id, attributes, { mean, usersRated }) {
  try {
    db.set(`data.${id}`, {
      id,
      updated: now,
      mean: [ mean ],
      slug: attributes.slug,
      usersRated: [ usersRated ],
      users: [ attributes.userCount ],
      title: attributes.canonicalTitle,
      poster: attributes.posterImage.medium,
      favorites: [ attributes.favoritesCount ]
    }).write()
  } catch (err) {
    console.error(err)
  }
}

async function update (id, attributes, { mean, usersRated }) {
  try {
    const latest = db.get(`data.${id}`).value()
    latest.updated = now
    latest.mean.push(mean)
    latest.slug = attributes.slug
    latest.usersRated.push(usersRated)
    latest.users.push(attributes.userCount)
    latest.title = attributes.canonicalTitle
    latest.poster = attributes.posterImage.medium
    latest.favorites.push(attributes.favoritesCount)
    db.set(`data.${id}`, latest).write()
  } catch (err) {
    console.error(err)
  }
}

async function check ({ id, attributes }) {
  try {
    const ratings = calcRatings(attributes.ratingFrequencies)
    if (!db.get(`data.${id}`).value()) await set(id, attributes, ratings)
    else await update(id, attributes, ratings)
  } catch (err) {
    console.error(err)
  }
}

async function remove ({ id }) {
  try {
    await db.unset(`data.${id}`).write()
  } catch (err) {
    console.error(err)
  }
}

async function getAiring (offset = 0) {
  try {
    const { data, meta, links } = await get('anime', { offset })
    for (let item of await data) {
      aired.splice(aired.indexOf(item.id), 1)
      await check(item)
    }
    await display(meta.count, data.length, offset)
    return links
  } catch (err) {
    console.error(err)
  }
}

// Updates shows that are airing this season, but have not yet aired
async function addUpcoming (offset = 0) {
  try {
    const { data, links } = await get('anime', {
      offset,
      upcoming: true
    })

    data.forEach(async anime => {
      const exists = db.get('data').find({ id: anime.id }).value()
      if (typeof exists === 'undefined') {
        await check(anime)
        console.log(`  Added ${anime.attributes.canonicalTitle}`)
      }
    })

    if (links.next) await addUpcoming(offset + 20)
  } catch (err) {
    console.error(err)
  }
}

// Updates shows that have finished - but aired during the season
// Additionally, also trims erroneous (old) shows from the data
function getAired () {
  try {
    aired.forEach(async id => {
      const { data } = await get('anime', { id })

      // Check if the show ended within this season
      // If not, it was an erroneous entry and shouldn't be in the season's data
      // at all - thus remove it entirely
      const ended = data.attributes.endDate
      const cutoff = new Date(now).getTime() - (3 * 30 * 24 * 60 * 60 * 1000)
      const endDate = new Date(ended === null ? new Date(now).getTime() + (24 * 60 * 60 * 100) : ended).getTime()
      if (endDate - cutoff > 0) await check(data)
      else await remove(data)

      console.log((endDate - cutoff > 0 ? 'Updated ' : 'Removed ') + data.attributes.canonicalTitle)
    })
  } catch (err) {
    console.error(err)
  }
}

(async function main (offset = 0) {
  try {
    const { next } = await getAiring(offset)
    if (next) await main(offset + 20)
    else {
      console.log('\nUpdating existing & upcoming anime:\n')
      await getAired()
      addUpcoming()
    }
  } catch (err) {
    console.error(err)
  }
})()
<|endoftext|>


<commit_before>import cx from 'classnames';
import * as d3 from 'd3';
import PropTypes from 'prop-types';
import React from 'react';
import {findDOMNode} from 'react-dom';

class Axis extends React.Component {
  componentDidMount() {
    this._renderAxis();
  }

  componentDidUpdate() {
    this._renderAxis();
  }

  render() {
    const {children, className, transform} = this.props;
    return (
      <g
        className={cx('axis', className)}
        transform={transform}>
        {children}
      </g>
    );
  }

  _renderAxis = () => {
    const {orient, scale, ticks, tickFormat, tickSize} = this.props;

    let axis;
    switch (orient) {
      case 'bottom':
        axis = d3.axisBottom(scale);
        break;
      case 'left':
        axis = d3.axisLeft(scale);
        break;
      case 'right':
        axis = d3.axisRight(scale);
        break;
      case 'top':
        axis = d3.axisTop(scale);
        break;
    }

    axis
      .ticks(ticks)
      .tickFormat(tickFormat)
      .tickSize(tickSize);

    d3.select(findDOMNode(this)).call(axis);
  };
}

Axis.propTypes = {
  orient: PropTypes.oneOf(['bottom', 'left', 'right', 'top']).isRequired,
  scale: PropTypes.func.isRequired,
  ticks: PropTypes.number,
  tickFormat: PropTypes.func,
  tickSize: PropTypes.number,
  transform: PropTypes.string,
};

Axis.defaultProps = {
  ticks: 5,
  tickSize: 6,
};

export default Axis;
<commit_msg>Remove default tick value in Axis<commit_after>import cx from 'classnames';
import * as d3 from 'd3';
import PropTypes from 'prop-types';
import React from 'react';
import {findDOMNode} from 'react-dom';

class Axis extends React.Component {
  componentDidMount() {
    this._renderAxis();
  }

  componentDidUpdate() {
    this._renderAxis();
  }

  render() {
    const {children, className, transform} = this.props;
    return (
      <g
        className={cx('axis', className)}
        transform={transform}>
        {children}
      </g>
    );
  }

  _renderAxis = () => {
    const {orient, scale, ticks, tickFormat, tickSize} = this.props;

    let axis;
    switch (orient) {
      case 'bottom':
        axis = d3.axisBottom(scale);
        break;
      case 'left':
        axis = d3.axisLeft(scale);
        break;
      case 'right':
        axis = d3.axisRight(scale);
        break;
      case 'top':
        axis = d3.axisTop(scale);
        break;
    }

    axis
      .ticks(ticks)
      .tickFormat(tickFormat)
      .tickSize(tickSize);

    d3.select(findDOMNode(this)).call(axis);
  };
}

Axis.propTypes = {
  orient: PropTypes.oneOf(['bottom', 'left', 'right', 'top']).isRequired,
  scale: PropTypes.func.isRequired,
  ticks: PropTypes.number,
  tickFormat: PropTypes.func,
  tickSize: PropTypes.number,
  transform: PropTypes.string,
};

Axis.defaultProps = {
  tickSize: 6,
};

export default Axis;
<|endoftext|>


<commit_before>/**
 * @copyright 2016-present, Prometheus Research, LLC
 */

import * as React from 'react';
import {isString} from 'lodash';

import * as I18N from './I18N';
import {create, css, component} from './stylesheet';

let stylesheet = create({
  Root: component.button({
    display: css.display.inlineBlock,
    verticalAlign: 'bottom',
    cursor: css.cursor.pointer,
    textAlign: css.textAlign.left,
    userSelect: css.none,
    WebkitUserSelect: css.none,
    whiteSpace: 'nowrap',
    overflow: 'hidden',
  }),
  Caption: component.div({
    display: css.display.inlineBlock,
  }),
  Icon: 'span',
  IconWrapper: component.div({
    display: css.display.inlineBlock,
  }),
});

/**
 * Button component.
 *
 * Button is clickable element with optional icon and/or caption.
 */
export default class ButtonBase extends React.Component {

  static propTypes = {
    /**
     * If button should be rendered as being pressed.
     */
    active: React.PropTypes.bool,

    /**
     * Button size.
     */
    size: React.PropTypes.oneOf(['x-small', 'small', 'normal', 'large']),

    /**
     * Button's icon.
     */
    icon: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.node
    ]),

    /**
     * Button's alternative icon (placed at the opposite direction to the
     * label).
     */
    iconAlt: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.node
    ]),

    href: React.PropTypes.string,

    Component: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.func,
    ]),

    /**
     * Button's caption.
     */
    children: React.PropTypes.node,
  };

  static contextTypes = I18N.contextTypes;

  static defaultProps = {
    size: 'normal',
    attach: {},
    stylesheet,
  };

  render() {
    let {
      children, icon, iconAlt = this.props.iconRight,
      disabled, active, size,
      attach,
      href,
      Component,
      groupVertically, groupHorizontally,
      variant,
      stylesheet: {Root, Caption, Icon, IconWrapper},
      textAlign, width, height,
      style,
      ...props
    } = this.props;
    let {i18n = I18N.defaultContext} = this.context;
    let sizeVariant = {
      'x-small': size === 'x-small',
      small: size === 'small',
      normal: size === 'normal',
      large: size === 'large',
    };
    variant = {
      active, disabled,
      attachLeft: attach.left,
      attachRight: attach.right,
      attachTop: attach.top,
      attachBottom: attach.bottom,
      groupVertically,
      groupHorizontally,
      rtl: i18n.dir === 'rtl',
      ltr: i18n.dir === 'ltr',
      ...sizeVariant,
      ...variant,
    };
    style = {
      width, height,
      textAlign,
      ...style,
    };
    if (href != null && Component == null) {
      Component = 'a';
    }
    if (isString(icon)) {
      icon = <Icon name={icon} />;
    }
    if (isString(iconAlt)) {
      iconAlt = <Icon name={iconAlt} />;
    }
    let caption = null;
    if (children) {
      caption =
{children}
;
    }
    let hasCaption = !!children;
    return (
      <Root
        Component={Component}
        {...props}
        href={href}
        disabled={disabled}
        variant={variant}
        style={style}
        aria-pressed={active}
        role="button">
        {icon ?
          <IconWrapper variant={{
            ...sizeVariant, hasCaption, leftPosition: true,
            rtl: i18n.dir === 'rtl',
            ltr: i18n.dir === 'ltr',
          }}>
            {icon}
          </IconWrapper> :
          null}
        {caption}
        {iconAlt ?
          <IconWrapper variant={{
            ...sizeVariant, hasCaption, rightPosition: true,
            rtl: i18n.dir === 'rtl',
            ltr: i18n.dir === 'ltr',
          }}>
            {iconAlt}
          </IconWrapper> :
          null}
      </Root>
    );
  }
}

<commit_msg>feat(button): add typings to <ButtonBase /><commit_after>/**
 * @copyright 2016-present, Prometheus Research, LLC
 * @flow
 */

import React, {Component} from 'react';

import type {I18NContext} from './I18N';

import * as I18N from './I18N';
import {style} from 'react-dom-stylesheet';
import * as css from 'react-dom-stylesheet/css';

let stylesheet = {
  Root: style('button', {
    display: css.display.inlineBlock,
    verticalAlign: 'bottom',
    cursor: css.cursor.pointer,
    textAlign: css.textAlign.left,
    userSelect: css.none,
    WebkitUserSelect: css.none,
    whiteSpace: 'nowrap',
    overflow: 'hidden',
  }),
  Caption: style('div', {
    display: css.display.inlineBlock,
  }),
  Icon: 'span',
  IconWrapper: style('div', {
    display: css.display.inlineBlock,
  }),
};

type ButtonBaseProps = {

  /**
    * If button should be rendered as being pressed.
    */
  active?: boolean;

  /**
    * If button should be rendered in disabled state.
    */
  disabled?: boolean;

  width?: number | string;
  height?: number | string;
  textAlign?: typeof css.textAlign;

  attach?: {left?: boolean; right?: boolean; top?: boolean; bottom?: boolean};

  groupVertically?: boolean;
  groupHorizontally?: boolean;

  /**
    * Button size.
    */
  size?: 'x-small' | 'small' | 'normal' | 'large';

  /**
    * Button's icon.
    */
  icon?: string | React.Element<*>;

  /**
    * Button's alternative icon (placed at the opposite direction to the
    * label).
    */
  iconAlt?: string | React.Element<*>;

  /**
    * Button's alternative icon (placed at the opposite direction to the
    * label).
    *
    * Deprecated.
    */
  iconRight?: string | React.Element<*>;

  href?: String;

  stylesheet: typeof stylesheet;

  variant?: Object;

  style?: Object;

  Component?: string | Function;

  children?: React.Element<*>;
};

type ButtonBasePropsDefault = {
  stylesheet: typeof stylesheet;
};

/**
 * Button component.
 *
 * Button is clickable element with optional icon and/or caption.
 */
export default class ButtonBase extends Component<ButtonBasePropsDefault, ButtonBaseProps, *> {

  context: I18NContext;

  static contextTypes = I18N.contextTypes;

  static defaultProps = {
    stylesheet,
  };

  render() {
    let {
      children, icon, iconAlt = this.props.iconRight,
      disabled, active,
      size = 'normal',
      attach = {},
      href,
      Component,
      groupVertically, groupHorizontally,
      variant,
      stylesheet: {Root, Caption, Icon, IconWrapper},
      textAlign, width, height,
      style,
      ...props
    } = this.props;
    let {i18n = I18N.defaultContext} = this.context;
    let sizeVariant = {
      'x-small': size === 'x-small',
      small: size === 'small',
      normal: size === 'normal',
      large: size === 'large',
    };
    variant = {
      active, disabled,
      attachLeft: attach.left,
      attachRight: attach.right,
      attachTop: attach.top,
      attachBottom: attach.bottom,
      groupVertically,
      groupHorizontally,
      rtl: i18n.dir === 'rtl',
      ltr: i18n.dir === 'ltr',
      ...sizeVariant,
      ...variant,
    };
    style = {
      width, height,
      textAlign,
      ...style,
    };
    if (href != null && Component == null) {
      Component = 'a';
    }
    if (typeof icon === 'string') {
      icon = <Icon name={icon} />;
    }
    if (typeof iconAlt === 'string') {
      iconAlt = <Icon name={iconAlt} />;
    }
    let caption = null;
    if (children) {
      caption =
{children}
;
    }
    let hasCaption = !!children;
    return (
      <Root
        Component={Component}
        {...props}
        href={href}
        disabled={disabled}
        variant={variant}
        style={style}
        aria-pressed={active}
        role="button">
        {icon ?
          <IconWrapper variant={{
            ...sizeVariant, hasCaption, leftPosition: true,
            rtl: i18n.dir === 'rtl',
            ltr: i18n.dir === 'ltr',
          }}>
            {icon}
          </IconWrapper> :
          null}
        {caption}
        {iconAlt ?
          <IconWrapper variant={{
            ...sizeVariant, hasCaption, rightPosition: true,
            rtl: i18n.dir === 'rtl',
            ltr: i18n.dir === 'ltr',
          }}>
            {iconAlt}
          </IconWrapper> :
          null}
      </Root>
    );
  }
}

<|endoftext|>


<commit_before>'use strict';

var slice = Array.prototype.slice;

function set(q, val) {
    var listener, next, ret;
    if (arguments.length > 1) { q.value = val; }
    if (q.listeners.length > 0) {
        listener = q.listeners.shift();
        if (typeof listener === 'function') {
            next = set.bind(null, q);
            ret = listener(q.value, next, q);
            if (ret !== next) {
                set(q, ret);
            }
        } else {
            set(q, listener);
        }
    }
    return q;
}

function get(q /*listeners*/) {
    var listeners = q.listeners;
    var isSettled = listeners.length < 1;
    listeners.push.apply(listeners, slice.call(arguments, 1));
    return isSettled ? set(q, q.value) : q;
}

function create(/*listeners*/) {
    return Object.seal({
        listeners: arguments.length ? slice.call(arguments) : [],
        value: undefined,
    });
}

module.exports = {
    create: create,
    get: get,
    set: set,
};
<commit_msg>removes superfluous conditional<commit_after>'use strict';

var slice = Array.prototype.slice;

function set(q, val) {
    var listener, next, ret;
    if (arguments.length > 1) { q.value = val; }
    if (q.listeners.length > 0) {
        listener = q.listeners.shift();
        if (typeof listener === 'function') {
            next = set.bind(null, q);
            ret = listener(q.value, next, q);
            if (ret !== next) {
                set(q, ret);
            }
        } else {
            set(q, listener);
        }
    }
    return q;
}

function get(q /*listeners*/) {
    var listeners = q.listeners;
    var isSettled = listeners.length < 1;
    listeners.push.apply(listeners, slice.call(arguments, 1));
    return isSettled ? set(q, q.value) : q;
}

function create(/*listeners*/) {
    return Object.seal({
        listeners: slice.call(arguments),
        value: undefined,
    });
}

module.exports = {
    create: create,
    get: get,
    set: set,
};
<|endoftext|>


<commit_before>(function($){$.fn.svgmagic=function(givenoptions){var defaultoptions={preloader:false,testmode:false,secure:false,callback:false,backgroundimage:false};var options=$.extend(defaultoptions,givenoptions);var ieversion=false,preloaderTimer=[];if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ieversion=new Number(RegExp.$1)}if(ieversion<9&&ieversion!=false||true==options.testmode){if(ieversion<8){if(typeof JSON!=="object"){JSON={}}(function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){escapable.lastIndex=0;return escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t==="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];if(a&&typeof a==="object"&&typeof a.toJSON==="function"){a=a.toJSON(e)}if(typeof rep==="function"){a=rep.call(t,e,a)}switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a){return"null"}gap+=indent;u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1){u[n]=str(n,a)||"null"}i=u.length===0?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+o+"]":"["+u.join(",")+"]";gap=o;return i}if(rep&&typeof rep==="object"){s=rep.length;for(n=0;n<s;n+=1){if(typeof rep[n]==="string"){r=rep[n];i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}else{for(r in a){if(Object.prototype.hasOwnProperty.call(a,r)){i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}i=u.length===0?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+o+"}":"{"+u.join(",")+"}";gap=o;return i}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","	":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;if(typeof JSON.stringify!=="function"){JSON.stringify=function(e,t,n){var r;gap="";indent="";if(typeof n==="number"){for(r=0;r<n;r+=1){indent+=" "}}else if(typeof n==="string"){indent=n}rep=t;if(t&&typeof t!=="function"&&(typeof t!=="object"||typeof t.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":e})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i==="object"){for(n in i){if(Object.prototype.hasOwnProperty.call(i,n)){r=walk(i,n);if(r!==undefined){i[n]=r}else{delete i[n]}}}}return reviver.call(e,t,i)}var j;text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}})()}var obj=this,images=[],domimages=[],cssimages=[];obj.each(function(){if($(this).attr("src")!=undefined){if($(this).attr("src").split(".").pop()=="svg"){$obj=$(this);var e=new Image;e.src=$(this).attr("src");images.push(e.src);domimages.push($obj);if(options.preloader!=false){preloaderTimer.push(setTimeout(function(){$obj.attr("src",options.preloader)},500))}}}});if(options.backgroundimage){if(obj.css("background-image")!=undefined){var bgsrc=obj.css("background-image").replace(/^url\(["']?/,"").replace(/["']?\)$/,"");if(bgsrc.split(".").pop()=="svg"){var image=new Image;image.src=bgsrc;images.push(image.src);cssimages.push(obj)}}}var data={svgsources:images,secure:options.secure};if(images.length>0){var i=0;$.ajax({dataType:"jsonp",url:"http://svgmagic.bitlabs.nl/converter.php",data:data,success:function(e){var t;for(t=0;t<domimages.length;t++){clearTimeout(preloaderTimer[t]);domimages[t].attr("src",e.results[t].url)}if(options.backgroundimage){for(t;t<domimages.length+cssimages.length;t++){var n=t-domimages.length;cssimages[n].css("background-image",'url("'+e.results[t].url+'")')}}if(options.callback){options.callback()}}})}}}})(jQuery)<commit_msg>Refresh .min with newer version<commit_after>(function($){$.fn.svgmagic=function(givenoptions){var defaultoptions={preloader:false,testmode:false,secure:false,callback:false,backgroundimage:false};var options=$.extend(defaultoptions,givenoptions);var ieversion=false,preloaderTimer=[];if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ieversion=new Number(RegExp.$1)}if(ieversion<9&&ieversion!=false||true==options.testmode){if(ieversion<8){if(typeof JSON!=="object"){JSON={}}(function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){escapable.lastIndex=0;return escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t==="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];if(a&&typeof a==="object"&&typeof a.toJSON==="function"){a=a.toJSON(e)}if(typeof rep==="function"){a=rep.call(t,e,a)}switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a){return"null"}gap+=indent;u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1){u[n]=str(n,a)||"null"}i=u.length===0?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+o+"]":"["+u.join(",")+"]";gap=o;return i}if(rep&&typeof rep==="object"){s=rep.length;for(n=0;n<s;n+=1){if(typeof rep[n]==="string"){r=rep[n];i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}else{for(r in a){if(Object.prototype.hasOwnProperty.call(a,r)){i=str(r,a);if(i){u.push(quote(r)+(gap?": ":":")+i)}}}}i=u.length===0?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+o+"}":"{"+u.join(",")+"}";gap=o;return i}}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","	":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;if(typeof JSON.stringify!=="function"){JSON.stringify=function(e,t,n){var r;gap="";indent="";if(typeof n==="number"){for(r=0;r<n;r+=1){indent+=" "}}else if(typeof n==="string"){indent=n}rep=t;if(t&&typeof t!=="function"&&(typeof t!=="object"||typeof t.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":e})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i==="object"){for(n in i){if(Object.prototype.hasOwnProperty.call(i,n)){r=walk(i,n);if(r!==undefined){i[n]=r}else{delete i[n]}}}}return reviver.call(e,t,i)}var j;text=String(text);cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}})()}var obj=this,images=[],domimages=[],cssimages=[];obj.each(function(){if($(this).attr("src")!=undefined){if($(this).attr("src").split(".").pop()=="svg"){$obj=$(this);var e=new Image;e.src=$(this).attr("src");images.push(e.src);domimages.push($obj);if(options.preloader!=false){preloaderTimer.push(setTimeout(function(){$obj.attr("src",options.preloader)},500))}}}});if(options.backgroundimage){if(obj.css("background-image")!="none"&&obj.css("background-image")!=undefined){var bgsrc=obj.css("background-image").replace(/^url\(["']?/,"").replace(/["']?\)$/,"");if(bgsrc.split(".").pop()=="svg"){var image=new Image;image.src=bgsrc;images.push(image.src);cssimages.push(obj)}}}var data={svgsources:images,secure:options.secure};if(images.length>0){var i=0;$.ajax({dataType:"jsonp",url:"http://svgmagic.bitlabs.nl/converter.php",data:data,success:function(e){var t;for(t=0;t<domimages.length;t++){clearTimeout(preloaderTimer[t]);domimages[t].attr("src",e.results[t].url)}if(options.backgroundimage){for(t;t<domimages.length+cssimages.length;t++){var n=t-domimages.length;cssimages[n].css("background-image",'url("'+e.results[t].url+'")')}}if(options.callback){options.callback()}}})}}}})(jQuery)<|endoftext|>


<commit_before>'use strict'

const PI = require('p-iteration')
const _isEmpty = require('lodash/isEmpty')
const runExample = require('../util/run_example')

module.exports = runExample({
  name: 'rest-close-positions',
  rest: { env: true, transform: true },
  ws: { env: true, transform: true, connect: true, auth: true },
  readline: true,
  params: {
    filterByMarket: null
  }
}, async ({
  debug, debugTable, rest, ws, params, readline
}) => {
  const { filterByMarket } = params
  const allPositions = await rest.positions()

  if (allPositions.length === 0) {
    debug('no open positions')
    return
  }

  debug(
    'found %d open positions on market(s) %s', allPositions.length,
    allPositions.map(({ symbol }) => symbol).join(',')
  )

  const positions = _isEmpty(filterByMarket)
    ? allPositions
    : allPositions.filter(({ symbol }) => symbol === filterByMarket)

  if (positions.length === 0) {
    debug('no positions match filter')
    return
  }

  const orders = positions.map(p => p.orderToClose(ws))

  debugTable({
    headers: [
      'ID', 'Symbol', 'Status', 'Amount', 'Base Price', 'P/L'
    ],

    rows: positions.map(p => ([
      p.id, p.symbol, p.status, p.amount, p.basePrice, p.pl
    ]))
  })

  orders.forEach(o => (debug('%s', o.toString())))
  debug('')

  const confirm = await readline.questionAsync(
    '>  Are you sure you want to submit the order(s) listed above? '
  )

  if (confirm.toLowerCase()[0] !== 'y') {
    return
  }

  debug('')

  ws.onOrderClose({}, ({ id, symbol, status }) => {
    debug('received confirmation of order %d closed on %s: %s', id, symbol, status)
  })

  await PI.forEachSeries(orders, o => o.submit())

  debug('')
  debug('closed %d positions', positions.length)
})
<commit_msg>update 'close_positions' example<commit_after>'use strict'

const PI = require('p-iteration')
const _isEmpty = require('lodash/isEmpty')
const WSv2 = require('../../lib/transports/ws2')
const { RESTv2 } = require('bfx-api-node-rest')
const { args: { apiKey, apiSecret }, debug, debugTable, readline } = require('../util/setup')

async function execute () {
  const ws = new WSv2({
    apiKey,
    apiSecret,
    transform: true
  })
  const rest = new RESTv2({
    apiKey,
    apiSecret,
    transform: true
  })
  const filterByMarket = null
  const allPositions = await rest.positions()
  await ws.open()
  await ws.auth()

  if (allPositions.length === 0) {
    debug('no open positions')
    await ws.close()
    readline.close()
    return
  }

  debug(
    'found %d open positions on market(s) %s', allPositions.length,
    allPositions.map(({ symbol }) => symbol).join(',')
  )

  const positions = _isEmpty(filterByMarket)
    ? allPositions
    : allPositions.filter(({ symbol }) => symbol === filterByMarket)

  if (positions.length === 0) {
    debug('no positions match filter')
    await ws.close()
    readline.close()
    return
  }

  const orders = positions.map(p => p.orderToClose(ws))

  debugTable({
    headers: [
      'ID', 'Symbol', 'Status', 'Amount', 'Base Price', 'P/L'
    ],

    rows: positions.map(p => ([
      p.id, p.symbol, p.status, p.amount, p.basePrice, p.pl
    ]))
  })

  orders.forEach(o => (debug('%s', o.toString())))
  debug('')

  const confirm = await readline.questionAsync(
    '>  Are you sure you want to submit the order(s) listed above? '
  )

  if (confirm.toLowerCase()[0] !== 'y') {
    await ws.close()
    readline.close()
    return
  }

  debug('')

  ws.onOrderClose({}, ({ id, symbol, status }) => {
    debug('received confirmation of order %d closed on %s: %s', id, symbol, status)
  })

  await PI.forEachSeries(orders, o => o.submit())

  debug('')
  debug('closed %d positions', positions.length)

  await ws.close()
  readline.close()
}

execute()
<|endoftext|>


<commit_before>function CrocSlider(root, slider, hover, focus, tr, t, tl, l, r, bl, b, br, bkg) {
	CrocBase.call(this, root);

	tr = tr || root.themer.getValue(arguments.callee, "tr");
	t = t || root.themer.getValue(arguments.callee, "t");
	tl = tl || root.themer.getValue(arguments.callee, "tl");
	l = l || root.themer.getValue(arguments.callee, "l");
	r = r || root.themer.getValue(arguments.callee, "r");
	bl = bl || root.themer.getValue(arguments.callee, "bl");
	b = b || root.themer.getValue(arguments.callee, "b");
	br = br || root.themer.getValue(arguments.callee, "br");
	bkg = bkg || root.themer.getValue(arguments.callee, "bkg");

	slider = slider || root.themer.getValue(arguments.callee, "slider");
	hover =  hover || root.themer.getValue(arguments.callee, "hover");
	focus = focus || root.themer.getValue(arguments.callee, "focus");

	//normal, hover, and focus are the valid modes
	this.mode = "normal";
	this.orientation = "horizontal";

	this.value = 0;
	this.maxValue = 100;
	this.minValue = 0;
	this.stepping = 1;

	this.groove = new CrocPanelBorder(root, tl, t, tr, l, r, bl, b, br, bkg);

	this.slider = new CrocImageSimple(root, slider);
	this.slider.setScaling('none');
	this.sliderHover = new CrocImageSimple(root, hover);
	this.sliderHover.setScaling('none');
	this.sliderFocus = new CrocImageSimple(root, focus);
	this.sliderFocus.setScaling('none');

	this.addEventListener('pointermove', function(e){

		if(!this.hasFocus()) {
			this.setMode('hover');
			this.getRoot().setCursor("pointer");
		}

		else {
			this.localPointToValue(e.local.x, e.local.y);
			this.getRoot().setCursor("pointer");
			this.event('valuechanged', this.getValue());
		}

		return false;
	});

	this.addEventListener('pointerleave', function(e) {

		if(!this.hasFocus()) {
			this.setMode('normal');
		}

		this.getRoot().setCursor("");

		return false;
	});

	this.addEventListener('pointerdown', function(e) {
		this.focus();

		this.localPointToValue(e.local.x, e.local.y);

		this.event('valuechanged', this.getValue());

		this.setMode('focus');
	});

	this.addEventListener('pointerup', function(e) {
		this.blur();
		this.setMode('hover');
	});

	this.addEventListener('pointerout', function(e) {
		this.blur();
		this.setMode('normal');
		this.getRoot().setCursor("");
	});
};

//We inherit everything from CrocBase
CrocSlider.prototype = Object.create(CrocBase.prototype);
CrocSlider.prototype.constructor = CrocSlider;

CrocSlider.prototype.getValue = function() {
	return this.value;
};

CrocSlider.prototype.setSize = function(size) {
	this.htmlTextfield.setSize(size);
	return;
};

CrocSlider.prototype.setColor = function(color) {
	this.htmlTextfield.setColor(color);
	return;
};

CrocSlider.prototype.setFont = function(font) {
	this.htmlTextfield.setFont(font);
	return;
};

CrocSlider.prototype.setMode = function(mode) {
	this.mode = mode;
	this.getRoot().repaint();
};

CrocSlider.prototype.setValue = function(value) {

	if(value < this.minValue) {
		value = this.minValue;
	}

	if(value > this.maxValue) {
		value = this.maxValue;
	}

	this.value = Math.round(value/this.stepping) * this.stepping;
	this.getRoot().repaint();

};

CrocSlider.prototype.setStepping = function(stepping) {

	this.stepping = stepping;
	this.setValue(this.value);
};

CrocSlider.prototype.setMaxValue = function(maxValue) {

	this.maxValue = maxValue;

	this.setValue(this.value);

};

CrocSlider.prototype.setMinValue = function(minValue) {
	this.minValue = minValue;

	this.setValue(this.value);
};

CrocSlider.prototype.getWidth = function () {
	if(this.orientation === 'verticle') {
		return this.slider.getWidth();
	}

	else {
		return this.width;
	}
};

CrocSlider.prototype.getHeight = function() {
	if(this.orientation === 'verticle') {
		return this.height;
	}

	else {
		return this.slider.getHeight();
	}
};

CrocSlider.prototype.setOrientation = function(orientation) {

	if(orientation.toLowerCase() === "verticle") {
		this.orientation = orientation;
	}

	else {
		this.orientation = "horizontal";
	}

	this.getRoot().repaint();
};

CrocSlider.prototype.localPointToValue = function(x, y) {
	var c = {x:x, y:y}

	if(this.orientation === 'verticle') {
		var value = (((c.y - (this.slider.getHeight() / 2)) * (this.maxValue - this.minValue))/(this.getHeight() - this.slider.getHeight())) + this.minValue;

		this.setValue(value);

	}

	else {
		var value = (((c.x - (this.slider.getWidth() / 2)) * (this.maxValue - this.minValue))/(this.getWidth() - this.slider.getWidth())) + this.minValue;

		this.setValue(value);
	}
};

CrocSlider.prototype.paint = function(context, width, height) {
	CrocBase.prototype.paint.call(this, context, width, height);

	context.save();

	var parentTransform = context.getCurrentTransform();

	var currentGroove = this.groove;
	var currentSlider = this.slider;

	switch(this.mode) {
		case 'normal':
			currentGroove = this.groove;
			currentSlider = this.slider;
			break;

		case 'hover':
			currentGroove = this.groove;
			currentSlider = this.sliderHover;
			break;

		case 'focus':
			currentGroove = this.groove;
			currentSlider = this.sliderFocus;
			break;

		default:
			break;
	}

	var tlw = currentGroove.topLeftImage.getWidth();
	var tlh = currentGroove.topLeftImage.getHeight();
	var brw = currentGroove.bottomRightImage.getWidth();
	var brh = currentGroove.bottomLeftImage.getHeight();

	if(this.orientation === 'verticle') {
		context.save();
		context.translate((currentSlider.getWidth() / 2) - ((tlw + brw) / 2), currentSlider.getHeight() / 2);
		currentGroove.paint(context, tlw + brw, this.getHeight() - currentSlider.getHeight());
		context.restore();

		var y = (((this.getHeight() - currentSlider.getHeight()) * (this.value - this.minValue)) / (this.maxValue - this.minValue));

		context.translate(0, y);
		currentSlider.paint(context);
	}

	else {
		context.save();
		context.translate(currentSlider.getWidth() / 2, (currentSlider.getHeight() / 2) - ((tlh + brh) / 2));
		currentGroove.paint(context, this.getWidth() - currentSlider.getWidth(), tlh + brh);
		context.restore();

		var x = (((this.getWidth() - currentSlider.getWidth()) * (this.value - this.minValue)) /  (this.maxValue - this.minValue));

		context.translate(x, 0);
		currentSlider.paint(context);
	}

	context.restore();

	return;
}
<commit_msg>Having the paint function check the visible flag for Slider<commit_after>function CrocSlider(root, slider, hover, focus, tr, t, tl, l, r, bl, b, br, bkg) {
	CrocBase.call(this, root);

	tr = tr || root.themer.getValue(arguments.callee, "tr");
	t = t || root.themer.getValue(arguments.callee, "t");
	tl = tl || root.themer.getValue(arguments.callee, "tl");
	l = l || root.themer.getValue(arguments.callee, "l");
	r = r || root.themer.getValue(arguments.callee, "r");
	bl = bl || root.themer.getValue(arguments.callee, "bl");
	b = b || root.themer.getValue(arguments.callee, "b");
	br = br || root.themer.getValue(arguments.callee, "br");
	bkg = bkg || root.themer.getValue(arguments.callee, "bkg");

	slider = slider || root.themer.getValue(arguments.callee, "slider");
	hover =  hover || root.themer.getValue(arguments.callee, "hover");
	focus = focus || root.themer.getValue(arguments.callee, "focus");

	//normal, hover, and focus are the valid modes
	this.mode = "normal";
	this.orientation = "horizontal";

	this.value = 0;
	this.maxValue = 100;
	this.minValue = 0;
	this.stepping = 1;

	this.groove = new CrocPanelBorder(root, tl, t, tr, l, r, bl, b, br, bkg);

	this.slider = new CrocImageSimple(root, slider);
	this.slider.setScaling('none');
	this.sliderHover = new CrocImageSimple(root, hover);
	this.sliderHover.setScaling('none');
	this.sliderFocus = new CrocImageSimple(root, focus);
	this.sliderFocus.setScaling('none');

	this.addEventListener('pointermove', function(e){

		if(!this.hasFocus()) {
			this.setMode('hover');
			this.getRoot().setCursor("pointer");
		}

		else {
			this.localPointToValue(e.local.x, e.local.y);
			this.getRoot().setCursor("pointer");
			this.event('valuechanged', this.getValue());
		}

		return false;
	});

	this.addEventListener('pointerleave', function(e) {

		if(!this.hasFocus()) {
			this.setMode('normal');
		}

		this.getRoot().setCursor("");

		return false;
	});

	this.addEventListener('pointerdown', function(e) {
		this.focus();

		this.localPointToValue(e.local.x, e.local.y);

		this.event('valuechanged', this.getValue());

		this.setMode('focus');
	});

	this.addEventListener('pointerup', function(e) {
		this.blur();
		this.setMode('hover');
	});

	this.addEventListener('pointerout', function(e) {
		this.blur();
		this.setMode('normal');
		this.getRoot().setCursor("");
	});
};

//We inherit everything from CrocBase
CrocSlider.prototype = Object.create(CrocBase.prototype);
CrocSlider.prototype.constructor = CrocSlider;

CrocSlider.prototype.getValue = function() {
	return this.value;
};

CrocSlider.prototype.setSize = function(size) {
	this.htmlTextfield.setSize(size);
	return;
};

CrocSlider.prototype.setColor = function(color) {
	this.htmlTextfield.setColor(color);
	return;
};

CrocSlider.prototype.setFont = function(font) {
	this.htmlTextfield.setFont(font);
	return;
};

CrocSlider.prototype.setMode = function(mode) {
	this.mode = mode;
	this.getRoot().repaint();
};

CrocSlider.prototype.setValue = function(value) {

	if(value < this.minValue) {
		value = this.minValue;
	}

	if(value > this.maxValue) {
		value = this.maxValue;
	}

	this.value = Math.round(value/this.stepping) * this.stepping;
	this.getRoot().repaint();

};

CrocSlider.prototype.setStepping = function(stepping) {

	this.stepping = stepping;
	this.setValue(this.value);
};

CrocSlider.prototype.setMaxValue = function(maxValue) {

	this.maxValue = maxValue;

	this.setValue(this.value);

};

CrocSlider.prototype.setMinValue = function(minValue) {
	this.minValue = minValue;

	this.setValue(this.value);
};

CrocSlider.prototype.getWidth = function () {
	if(this.orientation === 'verticle') {
		return this.slider.getWidth();
	}

	else {
		return this.width;
	}
};

CrocSlider.prototype.getHeight = function() {
	if(this.orientation === 'verticle') {
		return this.height;
	}

	else {
		return this.slider.getHeight();
	}
};

CrocSlider.prototype.setOrientation = function(orientation) {

	if(orientation.toLowerCase() === "verticle") {
		this.orientation = orientation;
	}

	else {
		this.orientation = "horizontal";
	}

	this.getRoot().repaint();
};

CrocSlider.prototype.localPointToValue = function(x, y) {
	var c = {x:x, y:y}

	if(this.orientation === 'verticle') {
		var value = (((c.y - (this.slider.getHeight() / 2)) * (this.maxValue - this.minValue))/(this.getHeight() - this.slider.getHeight())) + this.minValue;

		this.setValue(value);

	}

	else {
		var value = (((c.x - (this.slider.getWidth() / 2)) * (this.maxValue - this.minValue))/(this.getWidth() - this.slider.getWidth())) + this.minValue;

		this.setValue(value);
	}
};

CrocSlider.prototype.paint = function(context, width, height) {
	CrocBase.prototype.paint.call(this, context, width, height);

    if(!this.visible) {
        return;
    }

	context.save();

	var parentTransform = context.getCurrentTransform();

	var currentGroove = this.groove;
	var currentSlider = this.slider;

	switch(this.mode) {
		case 'normal':
			currentGroove = this.groove;
			currentSlider = this.slider;
			break;

		case 'hover':
			currentGroove = this.groove;
			currentSlider = this.sliderHover;
			break;

		case 'focus':
			currentGroove = this.groove;
			currentSlider = this.sliderFocus;
			break;

		default:
			break;
	}

	var tlw = currentGroove.topLeftImage.getWidth();
	var tlh = currentGroove.topLeftImage.getHeight();
	var brw = currentGroove.bottomRightImage.getWidth();
	var brh = currentGroove.bottomLeftImage.getHeight();

	if(this.orientation === 'verticle') {
		context.save();
		context.translate((currentSlider.getWidth() / 2) - ((tlw + brw) / 2), currentSlider.getHeight() / 2);
		currentGroove.paint(context, tlw + brw, this.getHeight() - currentSlider.getHeight());
		context.restore();

		var y = (((this.getHeight() - currentSlider.getHeight()) * (this.value - this.minValue)) / (this.maxValue - this.minValue));

		context.translate(0, y);
		currentSlider.paint(context);
	}

	else {
		context.save();
		context.translate(currentSlider.getWidth() / 2, (currentSlider.getHeight() / 2) - ((tlh + brh) / 2));
		currentGroove.paint(context, this.getWidth() - currentSlider.getWidth(), tlh + brh);
		context.restore();

		var x = (((this.getWidth() - currentSlider.getWidth()) * (this.value - this.minValue)) /  (this.maxValue - this.minValue));

		context.translate(x, 0);
		currentSlider.paint(context);
	}

	context.restore();

	return;
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name        QuizWiz : Rubrics
// @namespace   https://github.com/jamesjonesmath/canvancement
// @description Regrading and speed enhancements for Canvas quizzes
// @include     https://*.instructure.com/courses/*/gradebook/speed_grader?*
// @include     https://*.instructure.com/courses/*/quizzes/*/history?*
// @noframes
// @version     4
// @grant       none
// ==/UserScript==
(function() {
  'use strict';

  var config = {
    // Regrading methods may be 'disabled', 'enabled', or 'autorun'
    'methods' : {
      'unanswered' : 'autorun',
      'full_points' : 'disabled',
      'ma_allnone' : 'disabled',
      'ma_correct' : 'disabled',
      'ma_difference' : 'disabled',
      'fill_in_blanks' : 'disabled',
      'dropdowns' : 'disabled'
    },
    // Speed enhancements may be true or false
    'autoExpandComments' : true,
    'duplicateQuestionHeader' : true,
    'showButtonCounts' : true,
    'nextAfterUpdate' : true,
    'nextAfterComment' : true,
    'nextAfterRubric' : true,
    'nextRubricExpanded' : true
  };

  if (typeof QuizWiz !== 'function') {
    const script = document.createElement('script');
    script.src = 'https://gitcdn.link/repo/jamesjonesmath/canvancement/master/quizzes/quizwiz/src/qw-engine.js';
    script.onload = function() {
      QuizWiz(config);
    };
    document.head.appendChild(script);
  }
  else {
    QuizWiz(config);
  }

})();
<commit_msg>Forgot to bump the version number<commit_after>// ==UserScript==
// @name        QuizWiz : Rubrics
// @namespace   https://github.com/jamesjonesmath/canvancement
// @description Regrading and speed enhancements for Canvas quizzes
// @include     https://*.instructure.com/courses/*/gradebook/speed_grader?*
// @include     https://*.instructure.com/courses/*/quizzes/*/history?*
// @noframes
// @version     5
// @grant       none
// ==/UserScript==
(function() {
  'use strict';

  var config = {
    // Regrading methods may be 'disabled', 'enabled', or 'autorun'
    'methods' : {
      'unanswered' : 'autorun',
      'full_points' : 'disabled',
      'ma_allnone' : 'disabled',
      'ma_correct' : 'disabled',
      'ma_difference' : 'disabled',
      'fill_in_blanks' : 'disabled',
      'dropdowns' : 'disabled'
    },
    // Speed enhancements may be true or false
    'autoExpandComments' : true,
    'duplicateQuestionHeader' : true,
    'showButtonCounts' : true,
    'nextAfterUpdate' : true,
    'nextAfterComment' : true,
    'nextAfterRubric' : true,
    'nextRubricExpanded' : true
  };

  if (typeof QuizWiz !== 'function') {
    const script = document.createElement('script');
    script.src = 'https://gitcdn.link/repo/jamesjonesmath/canvancement/master/quizzes/quizwiz/src/qw-engine.js';
    script.onload = function() {
      QuizWiz(config);
    };
    document.head.appendChild(script);
  }
  else {
    QuizWiz(config);
  }

})();
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//         P5.GUI  :    Slider-Range Example 3                                //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// This example shows how to use objects variables to control the slider range
// and step for individual variables.

// seed color and alpha
var seedColor = '#ff00dd';
var bgColor = [0, 0, 0];
// seeds
const seeds = {
  seeds: 500,
  seedsMin: 1,
  seedsMax: 2000
};

// angle (phi)
const angle = {
  angle: 360 * (Math.sqrt(5)-1) / 2,
  angleMax: 360,
  angleStep: 0.1
}
// radius of the seed
const radius = {
  radius: 3,
  radiusMin: 0.5,
  radiusMax: 5,
  radiusStep: 0.1
};

// scale
const zoom = {
  zoom: 15,
  zoomMax: 50,
  zoomStep: 0.1
};

// seed opacity
const opacity = {
  opacity: 150,
  opacityMax: 255
};

////////////////////////////////////////////////////////////////////////////////

// the gui object
var gui;

function setup() {

  // all angles in degrees (0 .. 360)
  angleMode(DEGREES);

  // create a canvas that fills the window
  createCanvas(windowWidth, windowHeight);

  // create the GUI
  gui = createGui('slider-range-1');
  gui.addObject(seeds);
  gui.addObject(angle);
  gui.addObject(zoom);
  gui.addObject(radius);
  gui.addObject(opacity);

  // we keep the colors variables as non objects
  gui.addGlobals('seedColor', 'bgColor');

  // only call draw when then gui is changed
  noLoop();

}

function draw() {

  // hello darkness my old friend
  background(bgColor);

  // let the seeds be filleth
  var c = color(seedColor);
  fill(red(c), green(c), blue(c), opacity.opacity);
  stroke(0, opacity.opacity);

  // absolute radius
  var r = radius.radius * zoom.zoom;

  push();

  // go to the center of the sunflower
  translate(width/2, height/2);

  // rotate around the center while going outwards
  for(var i = 0; i < seeds.seeds; i++) {
    push();
    rotate(i * angle.angle);
    // distance to the center of the sunflower
    var d = sqrt(i + 0.5) * zoom.zoom;
    ellipse(d, 0, r, r);
    pop();
  }

  pop();

}

// dynamically adjust the canvas to the window
function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}
<commit_msg>Simplify setObject example<commit_after>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//         P5.GUI  :    Slider-Range Example 3                                //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// This example shows how to use *addObject* instead of *addGlobals*
// to provide gui parameters via a javascript object

let params = {

  // seeds
  seeds: 500,
  seedsMin: 1,
  seedsMax: 2000,

  // angle (phi)
  angle: 360 * (Math.sqrt(5)-1) / 2,
  angleMax: 360,
  angleStep: 0.1,

  // radius of the seed
  radius: 3,
  radiusMin: 0.5,
  radiusMax: 5,
  radiusStep: 0.1,

  seedColor: '#ff00dd',

  // scale
  zoom: 15,
  zoomMax: 50,
  zoomStep: 0.1,

  opacity: 150,
  opacityMax: 255,

  bgColor: [0, 0, 0]

};

////////////////////////////////////////////////////////////////////////////////

// the gui object
let gui;

function setup() {

  // all angles in degrees (0 .. 360)
  angleMode(DEGREES);

  // create a canvas that fills the window
  createCanvas(windowWidth, windowHeight);

  // create the GUI from a settings object
  gui = createGui('slider-range-1');
  gui.addObject(params);

  // only call draw when then gui is changed
  noLoop();

}

function draw() {

  // hello darkness my old friend
  background(params.bgColor);

  // let the seeds be filleth
  let c = color(params.seedColor);
  fill(red(c), green(c), blue(c), params.opacity);
  stroke(0, params.opacity);

  // absolute radius
  let r = params.radius * params.zoom;

  push();

  // go to the center of the sunflower
  translate(width/2, height/2);

  // rotate around the center while going outwards
  for(let i = 0; i < params.seeds; i++) {
    push();
    rotate(i * params.angle);
    // distance to the center of the sunflower
    let d = sqrt(i + 0.5) * params.zoom;
    ellipse(d, 0, r, r);
    pop();
  }

  pop();

}

// dynamically adjust the canvas to the window
function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}
<|endoftext|>


<commit_before>/*
 * SourceStream:
 * The SourceStream object implements the first two phases of translation.
 * It supplies methods for accessing a stream of characters from the source file.
 *
 * options -> Options object containing global information
 * string  -> Source code to stream from
 */

/*
 * 5.1.1.2 Translation Phases:
 *
 *   1. Physical source file multibyte characters are mapped, in an implementation-
 *      defined manner, to the source character set (introducing new-line characters for
 *      end-of-line indicators) if necessary. Trigraph sequences are replaced by
 *      corresponding single-character internal representations.
 *
 *   2. Each instance of a backslash character (\) immediately followed by a new-line
 *      character is deleted, splicing physical source lines to form logical source lines.
 *      Only the last backslash on any physical source line shall be eligible for being part
 *      of such a splice. A source file that is not empty shall end in a new-line character,
 *      which shall not be immediately preceded by a backslash character before any such
 *      splicing takes place.
 */

var SourceStream = function(options, string) {
	this.options = options;
	this.source = string;
	this.cursor = 0;
	this.line = 1;
	this.column = 1;
};

/*
 * Gets the character code of the source at the current cursor
 * and increments the cursor.
 */
SourceStream.prototype.nextch = function() {
	var ch;

	ch = this.peekch ();
	this.cursor++;

	/* If character is a newline character */
	if (ch === 10) {
		this.line++;
		this.column = 1;
	} else {
		this.column++;
	}

	return ch;
};

/*
 * Gets the character code of the source at the current cursor,
 * or zero if out-of-bounds
 */
SourceStream.prototype.peekch = function() {
	var ch;

	ch = this.source.charCodeAt (this.cursor) | 0;
	return ch;
};
<commit_msg>Join lines with an ending backslash<commit_after>/*
 * SourceStream:
 * The SourceStream object implements the first two phases of translation.
 * It supplies methods for accessing a stream of characters from the source file.
 *
 * options -> Options object containing global information
 * string  -> Source code to stream from
 */

/*
 * 5.1.1.2 Translation Phases:
 *
 *   1. Physical source file multibyte characters are mapped, in an implementation-
 *      defined manner, to the source character set (introducing new-line characters for
 *      end-of-line indicators) if necessary. Trigraph sequences are replaced by
 *      corresponding single-character internal representations.
 *
 *   2. Each instance of a backslash character (\) immediately followed by a new-line
 *      character is deleted, splicing physical source lines to form logical source lines.
 *      Only the last backslash on any physical source line shall be eligible for being part
 *      of such a splice. A source file that is not empty shall end in a new-line character,
 *      which shall not be immediately preceded by a backslash character before any such
 *      splicing takes place.
 */

var SourceStream = function(options, string) {
	this.options = options;
	this.source = string;
	this.cursor = 0;
	this.line = 1;
	this.column = 1;
};

/*
 * Gets the character code of the source at the current cursor
 * and increments the cursor.
 */
SourceStream.prototype.nextch = function() {
	var ch;

	ch = this.peekch ();
	this.cursor++;

	switch (ch) {
		case 92: /* backslash */
			if (this.peekch () == 10) {
				/* backslash and newline - join lines */
				this.line++;
				this.cursor++;
				return this.nextch ();
			}
			break;
		case 10: /* newline */
			this.line++;
			this.column = 1;
			break;
		default:
			this.column++;
			break;
	}

	return ch;
};

/*
 * Gets the character code of the source at the current cursor,
 * or zero if out-of-bounds
 */
SourceStream.prototype.peekch = function() {
	var ch;

	ch = this.source.charCodeAt (this.cursor) | 0;
	return ch;
};
<|endoftext|>