<commit_before><html>
	<body>
		<script src="inc/midi-parser.js"></script>
		<script src="inc/maker.js"></script>
		<form>
			<input type="file" name="fileupload" value="fileupload" id="fileupload">
			<label for="fileupload"> Select a file to upload</label>
		</form>
		<script type="text/javascript">
			var noteLetters = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]
			var notes = [];

			for (var num = 0; num < 128; num++) {
				notes.push({note: noteLetters[num%12], octave: Math.floor(num/12)});
			}

			var makerjs = require('makerjs');

			var scaleModes = {
				major: {
					ionian:  	[2,2,1,2,2,2],
					dorian: 	[2,1,2,2,2,1],
					phyrigian:  [1,2,2,2,1,2],
					lydian:     [2,2,2,1,2,2],
					mixolydian: [2,2,1,2,2,1],
					aeolian:    [2,1,2,2,1,2],
					locrian:    [1,2,2,1,2,2] 
				},
				harmonic_minor: {
					harmminor: 		[2,1,2,2,1,3],
					locriansharpsix:[1,2,2,1,3,1], 
					ionianaug:     	[2,2,1,3,1,2], 
					romanian: 		[2,1,3,1,2,1],
					phrygiandom:   	[1,3,1,2,1,2],
					lydiansharptwo: [3,1,2,1,2,2],
					ultralocrian:   [1,2,1,2,2,1]
				},
				melodic_minor: {
					jazz_minor: 		[2,1,2,2,2,2],
					dorianflatnine: 	[1,2,2,2,2,1],
					lydianaug: 			[2,2,2,2,1,2],
					lydiandom: 			[2,2,2,1,2,1],
					mixolydianflatsix: 	[2,2,1,2,1,2],
					semilocrian: 		[2,1,2,1,2,2],
					superlocrian: 		[1,2,1,2,2,2]
				}
			}

			function generateScale(root, scale, mode) {
				var result = [];
				var gaps = scaleModes[scale][mode];
				if (gaps === undefined) return undefined;
				result.push(root);
				var lastNoteNum = noteLetters.indexOf(root);
				for (var i=0; i<gaps.length; i++) {
					lastNoteNum += gaps[i];
					result.push(noteLetters[lastNoteNum%12]);
				}

				return result;
			}

			function generateMusicBox (startingNote, scale, size) {
				var result = [];
				result.push(startingNote);

				for (var i=1; i<size; i++) {
					var lastNote = result[i-1];
					var lastNoteNum = noteLetters.indexOf(lastNote.note);
					var noteNum = lastNoteNum;
					var lastOctave = lastNote.octave;

					do { //find next note that belongs to the scale
						noteNum += 1;
						noteNum %= 12;
					} while(scale.find(function(note){return note==noteLetters[noteNum]}) == undefined);

					result.push({note: noteLetters[noteNum], octave: (noteNum < lastNoteNum) ? (lastOctave + 1) : lastOctave}); //if noteNum < lastNoteNum, that means we are in a new octave
				}
				return result;
			}
			
			function downloadFile(fileName, fileText) {
				var element = document.createElement('a');
				element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileText));
				element.setAttribute('download', fileName);

				element.style.display = 'none';
				document.body.appendChild(element);

				element.click();

				document.body.removeChild(element);
			}
			
			function generateModel(notesAgainstTime, holeWidth, holeLength) {				
				var punchHoles = [];
				var model = { models: {}};
				for (var i=0; i<notesAgainstTime.length; i++) {
					var note = notesAgainstTime[i];
					var oval = new makerjs.models.Oval(holeLength,holeWidth);
					oval.units = makerjs.unitType.Millimeter;
					oval.origin = [note.x-(holeLength-(holeWidth/2)), note.y-(holeWidth/2)];
					punchHoles.push(oval);
				}
				model.models = punchHoles;
				return model;
			}

			var events = [];
			var notesAgainstTime = [];

			function processData(midiData) {
				console.log(midiData);

				var musicBox = generateMusicBox({note: "c", octave: 5}, generateScale("c", "major", "ionian"), 20);

				for(var i=0; i<midiData.tracks; i++){
					var currentTick = 0;
					for(var j=0; j<midiData.track[i].event.length; j++) {
						var event = midiData.track[i].event[j];
						currentTick+=event.deltaTime;
						if (event.type == 9){ //note on events
							var note = notes[event.data[0]];
							console.log(note);
							var index = musicBox.indexOf(musicBox.find(function(x){return x.note == note.note && x.octave == note.octave;}));
							console.log(index);
							if (index != -1) {
								events.push({type: "noteon", tick: currentTick, pitch: index, note: notes[event.data[0]], channel: event.channel, track: i});
							}
						}	
						else if (event.type == 255) { //meta events
							if(event.metaType == 81) { //tempo change events
								events.push({type: "tempochange", tempo: event.data, tick: currentTick});
							}
						}
					}
				}
				events.sort(function (a,b) {return a.tick > b.tick;});

				var timeAtLastTempoChange = 0;
				var ticksAtLastTempoChange = 0;
				var tempo = 500000;
				var ppq = midiData.timeDivision;

				for (var i=0; i<events.length; i++) {
					var event = events[i];

					if (event.type == "tempochange") {
						timeAtLastTempoChange += tempo * (event.tick - ticksAtLastTempoChange) / ppq;
						tempo = event.tempo;
						ticksAtLastTempoChange = event.tick;
						console.log("Tempo changed to " + tempo + " at " + timeAtLastTempoChange);
					}
					if (event.type == "noteon") {
						var rtime = timeAtLastTempoChange + tempo * (event.tick - ticksAtLastTempoChange) / ppq;
						notesAgainstTime.push({time: rtime, pitch: event.pitch, x: 0, y: 0});
					}
				}
				
				var machineTempo = 250000;
				var xOffset = 4;
				var yOffset = 3;
				var minDistanceBetweenSameNote = 8;
				var notesByPitch = [];
				
				for (var i=0; i<notesAgainstTime.length; i++) {
					var note = notesAgainstTime[i];
					console.log(note.pitch);
					note.x = (note.time/machineTempo)*xOffset;
					note.y = (note.pitch)*yOffset;
				}
				console.log(notesAgainstTime);

				var model = generateModel(notesAgainstTime, 1.5, 2);
				console.log(model);
				
				var svg = makerjs.exporter.toSVG(model, {units: makerjs.unitType.Millimeter});
				var dxf = makerjs.exporter.toDXF(model);
				
				downloadFile("Test.svg", svg);
				downloadFile("Test.dxf", dxf)
			};
			
			var file = document.getElementById("fileupload");
			MIDIParser.addListener(document.getElementById("fileupload"), processData);
		</script>
	</body>
</html><commit_msg>Change note.note to note.letter so that my head doesn't hurt<commit_after><html>
	<body>
		<script src="inc/midi-parser.js"></script>
		<script src="inc/maker.js"></script>
		<form>
			<input type="file" name="fileupload" value="fileupload" id="fileupload">
			<label for="fileupload"> Select a file to upload</label>
		</form>
		<script type="text/javascript">
			var noteLetters = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]
			var notes = [];

			for (var num = 0; num < 128; num++) {
				notes.push({letter: noteLetters[num%12], octave: Math.floor(num/12)});
			}

			var makerjs = require('makerjs');

			var scaleModes = {
				major: {
					ionian:  	[2,2,1,2,2,2],
					dorian: 	[2,1,2,2,2,1],
					phyrigian:  [1,2,2,2,1,2],
					lydian:     [2,2,2,1,2,2],
					mixolydian: [2,2,1,2,2,1],
					aeolian:    [2,1,2,2,1,2],
					locrian:    [1,2,2,1,2,2] 
				},
				harmonic_minor: {
					harmminor: 		[2,1,2,2,1,3],
					locriansharpsix:[1,2,2,1,3,1], 
					ionianaug:     	[2,2,1,3,1,2], 
					romanian: 		[2,1,3,1,2,1],
					phrygiandom:   	[1,3,1,2,1,2],
					lydiansharptwo: [3,1,2,1,2,2],
					ultralocrian:   [1,2,1,2,2,1]
				},
				melodic_minor: {
					jazz_minor: 		[2,1,2,2,2,2],
					dorianflatnine: 	[1,2,2,2,2,1],
					lydianaug: 			[2,2,2,2,1,2],
					lydiandom: 			[2,2,2,1,2,1],
					mixolydianflatsix: 	[2,2,1,2,1,2],
					semilocrian: 		[2,1,2,1,2,2],
					superlocrian: 		[1,2,1,2,2,2]
				}
			}

			function generateScale(root, scale, mode) {
				var result = [];
				var gaps = scaleModes[scale][mode];
				if (gaps === undefined) return undefined;
				result.push(root);
				var lastNoteNum = noteLetters.indexOf(root);
				for (var i=0; i<gaps.length; i++) {
					lastNoteNum += gaps[i];
					result.push(noteLetters[lastNoteNum%12]);
				}

				return result;
			}

			function generateMusicBox (startingNote, scale, size) {
				var result = [];
				result.push(startingNote);

				for (var i=1; i<size; i++) {
					var lastNote = result[i-1];
					var lastNoteNum = noteLetters.indexOf(lastNote.letter);
					var noteNum = lastNoteNum;
					var lastOctave = lastNote.octave;

					do { //find next note that belongs to the scale
						noteNum += 1;
						noteNum %= 12;
					} while(scale.find(function(note){return note==noteLetters[noteNum]}) == undefined);

					result.push({letter: noteLetters[noteNum], octave: (noteNum < lastNoteNum) ? (lastOctave + 1) : lastOctave}); //if noteNum < lastNoteNum, that means we are in a new octave
				}
				return result;
			}
			
			function downloadFile(fileName, fileText) {
				var element = document.createElement('a');
				element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileText));
				element.setAttribute('download', fileName);

				element.style.display = 'none';
				document.body.appendChild(element);

				element.click();

				document.body.removeChild(element);
			}
			
			function generateModel(notesAgainstTime, holeWidth, holeLength) {				
				var punchHoles = [];
				var model = { models: {}};
				for (var i=0; i<notesAgainstTime.length; i++) {
					var note = notesAgainstTime[i];
					var oval = new makerjs.models.Oval(holeLength,holeWidth);
					oval.units = makerjs.unitType.Millimeter;
					oval.origin = [note.x-(holeLength-(holeWidth/2)), note.y-(holeWidth/2)];
					punchHoles.push(oval);
				}
				model.models = punchHoles;
				return model;
			}

			var events = [];
			var notesAgainstTime = [];

			function processData(midiData) {
				console.log(midiData);

				var musicBox = generateMusicBox({letter: "c", octave: 5}, generateScale("c", "major", "ionian"), 20);

				for(var i=0; i<midiData.tracks; i++){
					var currentTick = 0;
					for(var j=0; j<midiData.track[i].event.length; j++) {
						var event = midiData.track[i].event[j];
						currentTick+=event.deltaTime;
						if (event.type == 9){ //note on events
							var note = notes[event.data[0]];
							console.log(note);
							var index = musicBox.indexOf(musicBox.find(function(x){return x.letter == note.letter && x.octave == note.octave;}));
							console.log(index);
							if (index != -1) {
								events.push({type: "noteon", tick: currentTick, pitch: index, note: notes[event.data[0]], channel: event.channel, track: i});
							}
						}	
						else if (event.type == 255) { //meta events
							if(event.metaType == 81) { //tempo change events
								events.push({type: "tempochange", tempo: event.data, tick: currentTick});
							}
						}
					}
				}
				events.sort(function (a,b) {return a.tick > b.tick;});

				var timeAtLastTempoChange = 0;
				var ticksAtLastTempoChange = 0;
				var tempo = 500000;
				var ppq = midiData.timeDivision;

				for (var i=0; i<events.length; i++) {
					var event = events[i];

					if (event.type == "tempochange") {
						timeAtLastTempoChange += tempo * (event.tick - ticksAtLastTempoChange) / ppq;
						tempo = event.tempo;
						ticksAtLastTempoChange = event.tick;
						console.log("Tempo changed to " + tempo + " at " + timeAtLastTempoChange);
					}
					if (event.type == "noteon") {
						var rtime = timeAtLastTempoChange + tempo * (event.tick - ticksAtLastTempoChange) / ppq;
						notesAgainstTime.push({time: rtime, pitch: event.pitch, x: 0, y: 0});
					}
				}
				
				var machineTempo = 250000;
				var xOffset = 4;
				var yOffset = 3;
				var minDistanceBetweenSameNote = 8;
				var notesByPitch = [];
				
				for (var i=0; i<notesAgainstTime.length; i++) {
					var note = notesAgainstTime[i];
					console.log(note.pitch);
					note.x = (note.time/machineTempo)*xOffset;
					note.y = (note.pitch)*yOffset;
				}
				console.log(notesAgainstTime);

				var model = generateModel(notesAgainstTime, 1.5, 2);
				console.log(model);
				
				var svg = makerjs.exporter.toSVG(model, {units: makerjs.unitType.Millimeter});
				var dxf = makerjs.exporter.toDXF(model);
				
				downloadFile("Test.svg", svg);
				downloadFile("Test.dxf", dxf)
			};
			
			var file = document.getElementById("fileupload");
			MIDIParser.addListener(document.getElementById("fileupload"), processData);
		</script>
	</body>
</html>
{'fraction_non_alphanumeric': 0.16884182877780513, 'fraction_numerical': 0.030534351145038167, 'mean_word_length': 3.0184696569920844, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2834259', 'n_tokens_mistral': 5865, 'n_tokens_neox': 4495, 'n_words': 872}