first, create a spreadsheet to receive the form submissions.
once you have a spreadsheet set up, navigate to the Apps Script page.
paste this script:
function read_byte(bytes) { let byte = bytes.splice(0, 1)[0]; return byte < 0 ? byte + 256 : byte; } function read_uint32(bytes) { let a = read_byte(bytes); let b = read_byte(bytes); let c = read_byte(bytes); let d = read_byte(bytes); return a | (b << 8) | (c << 16) | (d << 24); } function read_int32(bytes) { let a = read_byte(bytes); let b = read_byte(bytes); let c = read_byte(bytes); let d = bytes.splice(0, 1)[0]; return a | (b << 8) | (c << 16) | (d << 24); } function read_string(bytes) { let len = 0; let shift = 0; while (bytes.length > 0) { let byte = read_byte(bytes); len |= (byte & 0x7f) << shift; shift += 7; if (!(byte & 0x80)) break; } if (bytes.length < len) len = bytes.length; return String.fromCharCode(...bytes.splice(0, len)); } function parseSolution(bytes, metrics) { if (read_uint32(bytes) !== 7) { console.log("invalid solution file"); return; } metrics.puzzle = read_string(bytes); metrics.name = read_string(bytes); if (read_uint32(bytes) === 0) { console.log("solution file doesn't have metrics in it"); return; } let zero = read_uint32(bytes); metrics.cycles = read_uint32(bytes); let one = read_uint32(bytes); metrics.cost = read_uint32(bytes); let two = read_uint32(bytes); metrics.area = read_uint32(bytes); let three = read_uint32(bytes); metrics.instructions = read_uint32(bytes); if (zero !== 0 || one !== 1 || two !== 2 || three !== 3) { console.log("invalid solution file"); return; } metrics["track hexes"] = 0; let number_of_parts = read_uint32(bytes); for (let i = 0; i < number_of_parts; ++i) { let part_name = read_string(bytes); metrics[part_name] = (metrics[part_name] || 0) + 1; if (read_byte(bytes) != 1) { console.log("invalid solution file"); return; } read_int32(bytes); // u position read_int32(bytes); // v position read_int32(bytes); // size read_int32(bytes); // rotation read_uint32(bytes); // input/output index let number_of_instructions = read_uint32(bytes); for (let j = 0; j < number_of_instructions; ++j) { read_int32(bytes); // instruction offset read_byte(bytes); // instruction type } if (part_name === "track") { let number_of_track_hexes = read_uint32(bytes); for (let j = 0; j < number_of_track_hexes; ++j) { metrics["track hexes"]++; read_int32(bytes); // u position read_int32(bytes); // v position } } read_uint32(bytes); // arm number if (part_name === "pipe") { read_uint32(bytes); // conduit id let number_of_conduit_hexes = read_uint32(bytes); for (let j = 0; j < number_of_conduit_hexes; ++j) { read_int32(bytes); // u position read_int32(bytes); // v position } } } return metrics; } function onSubmit(e) { let ss = SpreadsheetApp.getActiveSpreadsheet(); for (var key in e.namedValues) { let value = e.namedValues[key]; if (typeof value !== 'object' || value.length === 0) continue; let url = value[0].split('https://drive.google.com/open?id='); if (url.length !== 2 || url[0] !== '') continue; let file = DriveApp.getFileById(url[1]); let bytes = file.getBlob().getBytes(); let metrics = {}; for (var k in e.namedValues) metrics[k] = e.namedValues[k][0]; parseSolution(bytes, metrics); let sheet = ss.getSheetByName(key); if (!sheet) { sheet = ss.insertSheet(key); sheet.setFrozenRows(1); } let row = []; for (var m in metrics) { let header = sheet.getRange(1, 1, 1, sheet.getMaxColumns()).getValues(); let col = header[0].indexOf(m); if (col < 0) { col = header[0].indexOf(''); sheet.getRange(1, col + 1).setValue(m); } row[col] = metrics[m]; } sheet.appendRow(row); } }
into the text box. once it's set up, the script will automatically fill in the metrics in a separate sheet every time a form is submitted. be sure to save the file after you paste.
to make the code run on each submission, set up a trigger.
choose the onSubmit function…
and have it run on form submit:
you'll have to go through this scary alert. there may be a way for me to submit my code to google to avoid this, but it would take more than 24 hours. let me know and i can do it if you want, though.
once you see this page, it should be all set up. try submitting a solution and see if it works.
the sheet it creates should look something like this. the name of the sheet is based on the question name in the form.