Difference between revisions of "Template:Groningen/message js"

(Created page with "var Message = {}; (function(){ /* Structure: * * Start: 'Spy': 3 * 3 base-pairs * Length: 16 bit number: 8 base-pairs * CRC32: 16 bit number: 8 base-pairs...")
 
Line 4: Line 4:
 
/* Structure:
 
/* Structure:
 
*
 
*
* Start:  'Spy':        3 * 3 base-pairs
+
* Start:  'Spy':        3 * 4 bases
* Length: 16 bit number: 8 base-pairs
+
* Pad:    'AAAA':        4 bases
* CRC32:  16 bit number: 8 base-pairs
+
* Subst:  1 character    1 * 4 bases
* Data:  '...':        length * 3 base-pairs
+
* Length: 16 bit number: 8 bases
* End:    'GEM':        3 * 3 base-pairs
+
* CRC32:  16 bit number: 8 bases
 +
* Data:  '...':        length * 4 bases
 +
* End:    'GEM':        3 * 4 bases
 
*/
 
*/
var lengths = {
+
var headDNA = EightBit.encodeStr('Spy'),
'start': 3 * 3,
+
tailDNA = EightBit.encodeStr('GEM'),
'len': 8,
+
padDNA = 'AAAA',
'crc': 8,
+
lengths = {
'end': 3 * 3
+
'start': headDNA.length,
};
+
'pad': 4,
var offsets = {};
+
'subst': 4,
 +
'len': 8,
 +
'crc': 8,
 +
'end': tailDNA.length
 +
},
 +
offsets = {},
 +
subOffs = {},
 +
subBase = 'A';
 +
 
offsets.start = 0;
 
offsets.start = 0;
offsets.len = offsets.start + lengths.start;
+
offsets.pad = offsets.start + lengths.start;
offsets.crc = offsets.len + lengths.len;
+
offsets.subst = offsets.pad + lengths.pad;
offsets.data = offsets.crc + lengths.crc;
+
offsets.len = offsets.subst + lengths.subst;
 +
subOffs.len = 0;
 +
subOffs.crc = subOffs.len + lengths.len;
 +
subOffs.data = subOffs.crc + lengths.crc;
 
 
 
var packDNA = function(dna, ext){
 
var packDNA = function(dna, ext){
var len = dna.length,
+
var subst = 0,
 +
len = dna.length,
 
crc = CRC.crc16(dna),
 
crc = CRC.crc16(dna),
dnaStart = SixFour.encodeStr('Spy'),
+
lenDNA = DNA.encodeUInt(len, lengths.len),
dnaEnd = SixFour.encodeStr('GEM'),
+
crcDNA = DNA.encodeUInt(crc, lengths.crc),
dnaLen = DNA.padUInt(DNA.encodeUInt(len), lengths.len),
+
suffixDNA = lenDNA + crcDNA + dna + tailDNA,
dnaCrc = DNA.padUInt(DNA.encodeUInt(crc), lengths.crc),
+
subst = DNA.Restrict.shortestAbsent(suffixDNA, subBase),
msg = dnaStart + dnaLen + dnaCrc + dna + dnaEnd;
+
substDNA = DNA.encodeUInt(subst.length, 4),
 +
msg = headDNA + padDNA + substDNA + DNA.Restrict.substitute(suffixDNA, subBase, subst);
 +
 +
var det = DNA.Restrict.detect(msg);
 +
if(det.length > 0){
 +
throw new Error("Restriction substitution failed");
 +
}
 
 
 
if(ext){
 
if(ext){
 
return {
 
return {
 
'msg': msg,
 
'msg': msg,
 +
'subst': subst.length,
 
'len': len,
 
'len': len,
 
'crc': crc,
 
'crc': crc,
'dnaStart': dnaStart,
+
'dnaStart': headDNA,
'dnaEnd': dnaEnd,
+
'dnaEnd': tailDNA,
'dnaLen': dnaLen,
+
'dnaSubst': substDNA,
'dnaCrc': dnaCrc
+
'dnaLen': lenDNA,
 +
'dnaCrc': crcDNA
 
};
 
};
 
}
 
}
Line 48: Line 70:
 
var unpackDNA = function(msg, ext){
 
var unpackDNA = function(msg, ext){
 
var dnaStart = msg.substr(offsets.start, lengths.start),
 
var dnaStart = msg.substr(offsets.start, lengths.start),
start = SixFour.decodeStr(dnaStart);
+
start = EightBit.decodeStr(dnaStart),
 +
pad = msg.substr(offsets.pad, lengths.pad);
 
 
 
if(start !== 'Spy'){ // start mismatch
 
if(start !== 'Spy'){ // start mismatch
Line 55: Line 78:
 
}
 
}
 
 
var dnaLen = msg.substr(offsets.len, lengths.len),
+
var dnaSubst = msg.substr(offsets.subst, lengths.subst),
 +
subst = DNA.decodeUInt(dnaSubst),
 +
suffixDNA = msg.substr(offsets.len),
 +
suffix = DNA.Restrict.restore(suffixDNA, subBase.repeat(subst)),
 +
dnaLen = suffix.substr(subOffs.len, lengths.len),
 
len = DNA.decodeUInt(dnaLen),
 
len = DNA.decodeUInt(dnaLen),
dnaCrc = msg.substr(offsets.crc, lengths.crc),
+
dnaCrc = suffix.substr(subOffs.crc, lengths.crc),
 
crc = DNA.decodeUInt(dnaCrc),
 
crc = DNA.decodeUInt(dnaCrc),
data = msg.substr(offsets.data, len);
+
data = suffix.substr(subOffs.data, len);
 
 
 
if(CRC.crc16(data) !== crc){ // checksum mismatch
 
if(CRC.crc16(data) !== crc){ // checksum mismatch
throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc);
+
throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc+" ("+data.length+" / "+len+")");
 
return null;
 
return null;
 
}
 
}
 
 
var dnaEnd = msg.substr(offsets.data + len, lengths.end),
+
var dnaEnd = suffix.substr(subOffs.data + len, lengths.end),
end = SixFour.decodeStr(dnaEnd);
+
end = EightBit.decodeStr(dnaEnd);
 
 
 
if(end !== 'GEM'){
 
if(end !== 'GEM'){
Line 77: Line 104:
 
return {
 
return {
 
'data': data,
 
'data': data,
 +
'subst': subst,
 
'len': len,
 
'len': len,
 
'crc': crc,
 
'crc': crc,
 
'dnaStart': dnaStart,
 
'dnaStart': dnaStart,
 +
'dnaSubst': dnaSubst,
 
'dnaEnd': dnaEnd,
 
'dnaEnd': dnaEnd,
 
'dnaLen': dnaLen,
 
'dnaLen': dnaLen,

Revision as of 13:16, 8 July 2016

var Message = {};

(function(){ /* Structure: * * Start: 'Spy': 3 * 4 bases * Pad: 'AAAA': 4 bases * Subst: 1 character 1 * 4 bases * Length: 16 bit number: 8 bases * CRC32: 16 bit number: 8 bases * Data: '...': length * 4 bases * End: 'GEM': 3 * 4 bases */ var headDNA = EightBit.encodeStr('Spy'), tailDNA = EightBit.encodeStr('GEM'), padDNA = 'AAAA', lengths = { 'start': headDNA.length, 'pad': 4, 'subst': 4, 'len': 8, 'crc': 8, 'end': tailDNA.length }, offsets = {}, subOffs = {}, subBase = 'A';

offsets.start = 0; offsets.pad = offsets.start + lengths.start; offsets.subst = offsets.pad + lengths.pad; offsets.len = offsets.subst + lengths.subst; subOffs.len = 0; subOffs.crc = subOffs.len + lengths.len; subOffs.data = subOffs.crc + lengths.crc;

var packDNA = function(dna, ext){ var subst = 0, len = dna.length, crc = CRC.crc16(dna), lenDNA = DNA.encodeUInt(len, lengths.len), crcDNA = DNA.encodeUInt(crc, lengths.crc), suffixDNA = lenDNA + crcDNA + dna + tailDNA, subst = DNA.Restrict.shortestAbsent(suffixDNA, subBase), substDNA = DNA.encodeUInt(subst.length, 4), msg = headDNA + padDNA + substDNA + DNA.Restrict.substitute(suffixDNA, subBase, subst);

var det = DNA.Restrict.detect(msg); if(det.length > 0){ throw new Error("Restriction substitution failed"); }

if(ext){ return { 'msg': msg, 'subst': subst.length, 'len': len, 'crc': crc, 'dnaStart': headDNA, 'dnaEnd': tailDNA, 'dnaSubst': substDNA, 'dnaLen': lenDNA, 'dnaCrc': crcDNA }; }

return msg; };

var unpackDNA = function(msg, ext){ var dnaStart = msg.substr(offsets.start, lengths.start), start = EightBit.decodeStr(dnaStart), pad = msg.substr(offsets.pad, lengths.pad);

if(start !== 'Spy'){ // start mismatch throw new Error("Start mismatch: '"+start+"' / 'Spy'"); return null; }

var dnaSubst = msg.substr(offsets.subst, lengths.subst), subst = DNA.decodeUInt(dnaSubst), suffixDNA = msg.substr(offsets.len), suffix = DNA.Restrict.restore(suffixDNA, subBase.repeat(subst)), dnaLen = suffix.substr(subOffs.len, lengths.len), len = DNA.decodeUInt(dnaLen), dnaCrc = suffix.substr(subOffs.crc, lengths.crc), crc = DNA.decodeUInt(dnaCrc), data = suffix.substr(subOffs.data, len);

if(CRC.crc16(data) !== crc){ // checksum mismatch throw new Error('CRC mismatch: '+CRC.crc16(data)+' / '+crc+" ("+data.length+" / "+len+")"); return null; }

var dnaEnd = suffix.substr(subOffs.data + len, lengths.end), end = EightBit.decodeStr(dnaEnd);

if(end !== 'GEM'){ throw new Error("End mismatch: '"+end+"' / 'GEM'"); return null; }

if(ext){ return { 'data': data, 'subst': subst, 'len': len, 'crc': crc, 'dnaStart': dnaStart, 'dnaSubst': dnaSubst, 'dnaEnd': dnaEnd, 'dnaLen': dnaLen, 'dnaCrc': dnaCrc }; }

return data; };

Message = { 'packDNA': packDNA, 'unpackDNA': unpackDNA }; })();