<commit_before>mini.Module(
	"engine/loop"
)
.requires(
	"basic/utils"
)
.defines(function(Utils) {
	var _Loop = function(callback, desiredTime) {
		var that = this;
		// -----------------------------------------------------------------------------

		// use requestAnimationFrame if available or setInterval otherwise

		// Find vendor prefix, if any
		var vendors = ['ms', 'moz', 'webkit', 'o'];
		for( var i = 0; i < vendors.length && !window.requestAnimationFrame; i++ ) {
			window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];
		}

		// Use requestAnimationFrame if available
		if( window.requestAnimationFrame ) {
			var next = 1,
				anims = {},
				lastFrame = {};

			that.start = function( callback, element ) {
				var current = next++;
				anims[current] = true;
				lastFrame[current] = new Date().getTime();

				var animate = function() {
					if( !anims[current] ) { return; } // deleted?
					window.requestAnimationFrame( animate, element );
					
					// setup time since last call
					var tm = new Date().getTime();
					var dt = (tm - lastFrame[current]) / 1000;
					lastFrame[current] = tm;

					callback(dt);
				};
				window.requestAnimationFrame( animate, element );
				return current;
			};

			that.stop = function( id ) {
				delete anims[id];
			};
		}

		// [set/clear]Interval fallback
		else {
			that.start = function( callback, element ) {
				return window.setInterval( callback, 1000/60 );
			};
			that.stop = function( id ) {
				window.clearInterval( id );
			};
		}
	};
	
	var Loop = function() {
		this.loop = new _Loop();
		this.callbacks = [];
		this.removals = {};
	};

	Loop.prototype.start = function(fn) {
		var fn = Utils.bind(this.update, this);
		this.__loopId__ = this.loop.start(fn);
		return this;
	};

	Loop.prototype.stop = function() {
		this.loop.stop(this.__loopId__);
		return this;
	};

	Loop.prototype.update = function(timePassed) {
		timePassed = 1/60;
		for(var index in this.callbacks)
			this.callbacks[index](timePassed);
	};

	Loop.prototype.add = function(context, func, keyForRemoval) {
		var bindFunction = Utils.bind(func, context);
		
		if(typeof keyForRemoval !== "undefined") {
			this.removals[keyForRemoval] = bindFunction;
		}
		this.callbacks.push(bindFunction);
		return this;
	};

	Loop.prototype.remove = function(keyForRemoval) {
		var functionToRemove = this.removals[keyForRemoval];
		var index = this.callbacks.indexOf(functionToRemove);
		if (index !== - 1) {
			this.callbacks.splice( index, 1 );
		}
		return this;
	};

	Loop.prototype.clear = function() {
		this.callbacks.length = 0;
		return this;
	};
	
	return Loop;
});
<commit_msg>Loop as mini.Class<commit_after>mini.Module(
	"engine/loop"
)
.requires(
	"basic/utils"
)
.defines(function(Utils) {
	var _Loop = function(callback, desiredTime) {
		var that = this;
		// -----------------------------------------------------------------------------

		// use requestAnimationFrame if available or setInterval otherwise

		// Find vendor prefix, if any
		var vendors = ['ms', 'moz', 'webkit', 'o'];
		for( var i = 0; i < vendors.length && !window.requestAnimationFrame; i++ ) {
			window.requestAnimationFrame = window[vendors[i]+'RequestAnimationFrame'];
		}

		// Use requestAnimationFrame if available
		if( window.requestAnimationFrame ) {
			var next = 1,
				anims = {},
				lastFrame = {};

			that.start = function( callback, element ) {
				var current = next++;
				anims[current] = true;
				lastFrame[current] = new Date().getTime();

				var animate = function() {
					if( !anims[current] ) { return; } // deleted?
					window.requestAnimationFrame( animate, element );
					
					// setup time since last call
					var tm = new Date().getTime();
					var dt = (tm - lastFrame[current]) / 1000;
					lastFrame[current] = tm;

					callback(dt);
				};
				window.requestAnimationFrame( animate, element );
				return current;
			};

			that.stop = function( id ) {
				delete anims[id];
			};
		}

		// [set/clear]Interval fallback
		else {
			that.start = function( callback, element ) {
				return window.setInterval( callback, 1000/60 );
			};
			that.stop = function( id ) {
				window.clearInterval( id );
			};
		}
	};
	
	var Loop = mini.Class.subclass({
		initialize: function() {
			this.loop = new _Loop();
			this.callbacks = [];
			this.removals = {};
		},

		start: function(fn) {
			var fn = Utils.bind(this.update, this);
			this.__loopId__ = this.loop.start(fn);
			return this;
		},
	
		stop: function() {
			this.loop.stop(this.__loopId__);
			return this;
		},
	
		update: function(timePassed) {
			timePassed = 1/60;
			for(var index in this.callbacks)
				this.callbacks[index](timePassed);
		},
	
		add: function(context, func, keyForRemoval) {
			var bindFunction = Utils.bind(func, context);
			
			if(typeof keyForRemoval !== "undefined") {
				this.removals[keyForRemoval] = bindFunction;
			}
			this.callbacks.push(bindFunction);
			return this;
		},
	
		remove: function(keyForRemoval) {
			var functionToRemove = this.removals[keyForRemoval];
			var index = this.callbacks.indexOf(functionToRemove);
			if (index !== - 1) {
				this.callbacks.splice( index, 1 );
			}
			return this;
		},
	
		clear: function() {
			this.callbacks.length = 0;
			return this;
		}
	});

	return Loop;
});

{'fraction_non_alphanumeric': 0.16407098877218398, 'fraction_numerical': 0.0065193770373053244, 'mean_word_length': 2.377981651376147, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4395729', 'n_tokens_mistral': 2138, 'n_tokens_neox': 1711, 'n_words': 380}