<commit_before> <!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Video player</title>

	<link rel="stylesheet" type="text/css" href="encode.css">
	<script src="../js/third-party/jquery-1.8.1.js" type="text/javascript"></script>
	<script src="../js/third-party/base64.js" type="text/javascript"></script>
	<script src="../js/third-party/underscore-min.js" type="text/javascript"></script>
	<script src="../js/third-party/FileSaver.js" type="text/javascript"></script>
	<script src="../js/third-party/clusterfck.js" type="text/javascript"></script>
	<script src="../js/util.js" type="text/javascript"></script>
	<script src="../js/tileset.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder-repeated.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder-similar.js" type="text/javascript"></script>
</head>

<body class="loading" style="background: gray">
	<div class="loading-messsage">Loading...</div>
	
	<div>
		<button id="play-button">Play</button>
		<canvas id="video-output" class="video-player"></canvas>
	</div>

	<script>
		$(document).ready(function(){
			//var videoName = '../data/encoded-video-20x15-30fps.json';						
			//var videoName = '../data/encoded-video-20x15-30fps-mirrored-tiles.json';						
			var videoName = '../data/encoded-video-20x15-30fps-tilebank.json';
		
			$.ajax(videoName).then(function(json){			
				window.originalVideo = json;
				
				var videoOutput = $('#video-output')[0];
				videoOutput.width = originalVideo.tileCountX * 8;
				videoOutput.height = originalVideo.tileCountY * 8;
				$(videoOutput).css({
					width: videoOutput.width * 2,
					width: videoOutput.height * 2
				});
				
				var ctx = videoOutput.getContext('2d');
				var imgData = ctx.getImageData(0, 0, videoOutput.width, videoOutput.height);
				
				function renderSimpleFrame(frame) {
					var w = videoOutput.width,
						h = videoOutput.height;

					// Loop through rows of tiles
					for (var ty = 0; ty != originalVideo.tileCountY; ty++) { 
						// Loop through columns of tiles
						for (var tx = 0; tx != originalVideo.tileCountX; tx++) { 
							// Gets current tile
							var tileNumber = frame.map[ty][tx],
								tile = TileSet.hexToTile(frame.tiles[tileNumber]);
							
							// Loop through rows of tile pixels
							for (var py = 0; py != 8; py++) { 
								// Loop through columns of tile pixels
								for (var px = 0; px != 8; px++) { 
									var x = tx * 8 + px,
										y = ty * 8 + py,
										ofs = (y * w + x) * 4,
										color = tile[py][px] * 255;
									imgData.data[ofs] = color;
									imgData.data[ofs + 1] = color;
									imgData.data[ofs + 2] = color;
									imgData.data[ofs + 3] = 255;
								}
							}
						}
					}
				}
				
				function renderMirroredFrame(frame) {
					var w = videoOutput.width,
						h = videoOutput.height;

					// Loop through rows of tiles
					for (var ty = 0; ty != originalVideo.tileCountY; ty++) { 
						// Loop through columns of tiles
						for (var tx = 0; tx != originalVideo.tileCountX; tx++) { 
							// Gets current tile
							var tileData = frame.map[ty][tx],
								tile = TileSet.hexToTile(frame.tiles[tileData.n]);
							
							// Loop through rows of tile pixels
							for (var py = 0; py != 8; py++) { 
								// Loop through columns of tile pixels
								for (var px = 0; px != 8; px++) { 
									var x = tx * 8 + px,
										y = ty * 8 + py,
										fx = tileData.h ? 7 - px : px,
										fy = tileData.v ? 7 - py : py,
										ofs = (y * w + x) * 4,
										color = tile[fy][fx] * 255;
										
									if (tileData.i) {
										color = color ? 0 : 255;
									}
										
									imgData.data[ofs] = color;
									imgData.data[ofs + 1] = color;
									imgData.data[ofs + 2] = color;
									imgData.data[ofs + 3] = 255;
								}
							}
						}
					}
				}

				function renderTileBankFrame(frame) {
					if (!renderTileBankFrame.prevFrame || renderTileBankFrame.prevFrame > frame.number) {
						renderTileBankFrame.prevFrameNumber = 0;
						renderTileBankFrame.loadedTiles = [];
					}
					
					if (renderTileBankFrame.prevFrameNumber == frame.number) {
						// Didn't change frame; nothing to do.
						return;
					}
					
					for (var i = renderTileBankFrame.prevFrameNumber; i != frame.number; i++) {
						var tmpFrame = originalVideo.frames[i];
						
						if (tmpFrame.tilesFromBank) {
							tmpFrame.tilesFromBank.forEach(function(info){
								renderTileBankFrame.loadedTiles[info.dest] = originalVideo.tileBank[info.orig];
							});
						}
						
						if (tmpFrame.tilesToStream) {
							tmpFrame.tilesToStream.forEach(function(info){
								renderTileBankFrame.loadedTiles[info.dest] = info.tile;
							});
						}
					}
					
					renderMirroredFrame({
						tiles: renderTileBankFrame.loadedTiles,
						map: frame.map
					});
					
					renderTileBankFrame.prevFrameNumber = frame.number;
				}
				
				function drawFrame(frameNumber) {
					renderFrame(originalVideo.frames[frameNumber]);
					ctx.putImageData(imgData, 0, 0);
				}
				
				var renderFrame = renderTileBankFrame;
				var startTime = 0;
				function requestFrame() {
					if (!startTime) {
						startTime = new Date().getTime();
					}									
					
					var delta = new Date().getTime() - startTime;<commit_msg>Made the player support the encoded map<commit_after> <!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Video player</title>

	<link rel="stylesheet" type="text/css" href="encode.css">
	<script src="../js/third-party/jquery-1.8.1.js" type="text/javascript"></script>
	<script src="../js/third-party/base64.js" type="text/javascript"></script>
	<script src="../js/third-party/underscore-min.js" type="text/javascript"></script>
	<script src="../js/third-party/FileSaver.js" type="text/javascript"></script>
	<script src="../js/third-party/clusterfck.js" type="text/javascript"></script>
	<script src="../js/util.js" type="text/javascript"></script>
	<script src="../js/tileset.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder-repeated.js" type="text/javascript"></script>
	<script src="../js/tileset-encoder-similar.js" type="text/javascript"></script>
</head>

<body class="loading" style="background: gray">
	<div class="loading-messsage">Loading...</div>
	
	<div>
		<button id="play-button">Play</button>
		<canvas id="video-output" class="video-player"></canvas>
	</div>

	<script>
		$(document).ready(function(){
			//var videoName = '../data/encoded-video-20x15-30fps.json';						
			//var videoName = '../data/encoded-video-20x15-30fps-mirrored-tiles.json';						
			//var videoName = '../data/encoded-video-20x15-30fps-tilebank.json';
			var videoName = '../data/encoded-video-20x15-30fps-deltarle.json';
		
			$.ajax(videoName).then(function(json){			
				window.originalVideo = json;
				
				var videoOutput = $('#video-output')[0];
				videoOutput.width = originalVideo.tileCountX * 8;
				videoOutput.height = originalVideo.tileCountY * 8;
				$(videoOutput).css({
					width: videoOutput.width * 2,
					width: videoOutput.height * 2
				});
				
				var ctx = videoOutput.getContext('2d');
				var imgData = ctx.getImageData(0, 0, videoOutput.width, videoOutput.height);
				
				function renderSimpleFrame(frame) {
					var w = videoOutput.width,
						h = videoOutput.height;

					// Loop through rows of tiles
					for (var ty = 0; ty != originalVideo.tileCountY; ty++) { 
						// Loop through columns of tiles
						for (var tx = 0; tx != originalVideo.tileCountX; tx++) { 
							// Gets current tile
							var tileNumber = frame.map[ty][tx],
								tile = TileSet.hexToTile(frame.tiles[tileNumber]);
							
							// Loop through rows of tile pixels
							for (var py = 0; py != 8; py++) { 
								// Loop through columns of tile pixels
								for (var px = 0; px != 8; px++) { 
									var x = tx * 8 + px,
										y = ty * 8 + py,
										ofs = (y * w + x) * 4,
										color = tile[py][px] * 255;
									imgData.data[ofs] = color;
									imgData.data[ofs + 1] = color;
									imgData.data[ofs + 2] = color;
									imgData.data[ofs + 3] = 255;
								}
							}
						}
					}
				}
				
				function renderMirroredFrame(frame) {
					var w = videoOutput.width,
						h = videoOutput.height;

					// Loop through rows of tiles
					for (var ty = 0; ty != originalVideo.tileCountY; ty++) { 
						// Loop through columns of tiles
						for (var tx = 0; tx != originalVideo.tileCountX; tx++) { 
							// Gets current tile
							var tileData = frame.map[ty][tx],
								tile = TileSet.hexToTile(frame.tiles[tileData.n]);
							
							// Loop through rows of tile pixels
							for (var py = 0; py != 8; py++) { 
								// Loop through columns of tile pixels
								for (var px = 0; px != 8; px++) { 
									var x = tx * 8 + px,
										y = ty * 8 + py,
										fx = tileData.h ? 7 - px : px,
										fy = tileData.v ? 7 - py : py,
										ofs = (y * w + x) * 4,
										color = tile[fy][fx] * 255;
										
									if (tileData.i) {
										color = color ? 0 : 255;
									}
										
									imgData.data[ofs] = color;
									imgData.data[ofs + 1] = color;
									imgData.data[ofs + 2] = color;
									imgData.data[ofs + 3] = 255;
								}
							}
						}
					}
				}

				function renderTileBankFrame(frame) {
					if (!renderTileBankFrame.prevFrame || renderTileBankFrame.prevFrame > frame.number) {
						renderTileBankFrame.prevFrameNumber = 0;
						renderTileBankFrame.loadedTiles = [];
					}
					
					if (renderTileBankFrame.prevFrameNumber == frame.number) {
						// Didn't change frame; nothing to do.
						return;
					}
					
					for (var i = renderTileBankFrame.prevFrameNumber; i != frame.number; i++) {
						var tmpFrame = originalVideo.frames[i];
						
						if (tmpFrame.tilesFromBank) {
							tmpFrame.tilesFromBank.forEach(function(info){
								renderTileBankFrame.loadedTiles[info.dest] = originalVideo.tileBank[info.orig];
							});
						}
						
						if (tmpFrame.tilesToStream) {
							tmpFrame.tilesToStream.forEach(function(info){
								renderTileBankFrame.loadedTiles[info.dest] = info.tile;
							});
						}
					}
					
					renderMirroredFrame({
						tiles: renderTileBankFrame.loadedTiles,
						map: frame.map
					});
					
					renderTileBankFrame.prevFrameNumber = frame.number;
				}
				
				function renderDeltaRleFrame(frame) {
					if (!renderDeltaRleFrame.prevFrame || renderDeltaRleFrame.prevFrame > frame.number) {
						renderDeltaRleFrame.prevFrameNumber = 0;						
						renderDeltaRleFrame.map = {
							tiles: _.times(originalVideo.tileCountX * originalVideo.tileCountY, _.constant({n: 0})),
							attrs: _.times(originalVideo.tileCountX * originalVideo.tileCountY, _.constant({}))
						};
					}
					
					if (renderDeltaRleFrame.prevFrameNumber == frame.number) {
						// Didn't change frame; nothing to do.
						return;
					}
					
					// Copy the next n bytes, unmodified
					var VERBATIM = 'v';
					// Repeat the next byte n times
					var REPEAT = 'r';
					// Skip the next n bytes
					var SKIP = 's';
					// Sets the top bits of the length of the next command
					var BOOST_LENGTH = 'b';
					// End this frame
					var END = 'e';
					var MAX_RLE_LENGTH = 64;
					
					function decodeDeltaRle(buffer, commands) {
						var bufPos = 0, cmdPos = 0, boost = 0;
						while (commands[cmdPos].c != END) {
							var cmd = commands[cmdPos],
								len = cmd.l + boost;
								
							switch (cmd.c) {
							
								case VERBATIM: {
									// Copies the next n commands
									cmdPos++;
									for (var i = 0; i != len; i++) {
										buffer[bufPos] = commands[cmdPos];
										bufPos++; cmdPos++;									
									}
									boost = 0;
									break;
								}
								
								case REPEAT: {
									// Copies the next command n times
									cmdPos++;
									for (var i = 0; i != len; i++) {
										buffer[bufPos] = commands[cmdPos];
										bufPos++; 
									}
									cmdPos++;
									boost = 0;
									break;
								}

								case SKIP: {
									// Keeps unchanged the next n bufer positions
									cmdPos++;
									bufPos += len;
									boost = 0;
									break;
								}

								case BOOST_LENGTH: {
									// Sets the top bits of the length of the next command
									cmdPos++;
									boost = cmd.l * MAX_RLE_LENGTH;
									break;
								}
								
								default: {
									buffer[bufPos] = commands[cmdPos];
									bufPos++; cmdPos++;
									boost = 0;
								}
							}
						}						
					}
					
					for (var i = renderDeltaRleFrame.prevFrameNumber; i != frame.number; i++) {
						var tmpFrame = originalVideo.frames[i];
						decodeDeltaRle(renderDeltaRleFrame.map.tiles, tmpFrame.map.tiles);
						decodeDeltaRle(renderDeltaRleFrame.map.attrs, tmpFrame.map.attrs);
						
						var flatMap = _.zip(renderDeltaRleFrame.map.tiles, renderDeltaRleFrame.map.attrs).map(function(pair){ 
							return _.extend({
								n: pair[0].n + (pair[1].t << 8 || 0) 
							}, _.pick(pair[1], 'v', 'h', 'i'));
						});
						
						renderTileBankFrame(_.chain(tmpFrame).omit('map').extend({
							map: Util.inGroupsOf(flatMap, originalVideo.tileCountX)
						}).value());
					}
					
//					renderTileBankFrame();
					
					renderDeltaRleFrame.prevFrameNumber = frame.number;
				}
				
				function drawFrame(frameNumber) {
					renderFrame(originalVideo.frames[frameNumber]);
					ctx.putImageData(imgData, 0, 0);
				}
				
				var renderFrame = renderDeltaRleFrame;
				var startTime = 0;
				function requestFrame() {
					if (!startTime) {
						startTime = new Date().getTime();
					}									
					
					var delta = new Date().getTime() - startTime;
{'fraction_non_alphanumeric': 0.1456925068315835, 'fraction_numerical': 0.01294405292679419, 'mean_word_length': 2.1478044363965596, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 82, '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': '305630', 'n_tokens_mistral': 6610, 'n_tokens_neox': 4387, 'n_words': 964}