Lorenz.mjs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /**
  2. * Emulation of the Lorenz SZ40/42a/42b cipher attachment.
  3. *
  4. * @author VirtualColossus [martin@virtualcolossus.co.uk]
  5. * @copyright Crown Copyright 2019
  6. * @license Apache-2.0
  7. */
  8. import Operation from "../Operation";
  9. import OperationError from "../errors/OperationError";
  10. /**
  11. * Lorenz operation
  12. */
  13. class Lorenz extends Operation {
  14. /**
  15. * Lorenz constructor
  16. */
  17. constructor() {
  18. super();
  19. this.name = "Lorenz";
  20. this.module = "Default";
  21. this.description = "Enciphers characters using the World War 2 German Lorenz SZ cipher attachment.";
  22. this.infoURL = "https://lorenz.virtualcolossus.co.uk";
  23. this.inputType = "string";
  24. this.outputType = "string";
  25. this.args = [
  26. {
  27. name: "Model",
  28. type: "option",
  29. "value": ["SZ40", "SZ42a", "SZ42b"]
  30. },
  31. {
  32. name: "Wheel Pattern",
  33. type: "argSelector",
  34. "value": [
  35. {
  36. name: "KH Pattern",
  37. off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
  38. },
  39. {
  40. name: "ZMUG Pattern",
  41. off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
  42. },
  43. {
  44. name: "BREAM Pattern",
  45. off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
  46. },
  47. {
  48. name: "No Pattern",
  49. off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
  50. },
  51. {
  52. name: "Custom",
  53. on: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
  54. }
  55. ]
  56. },
  57. {
  58. name: "KT-Schalter",
  59. type: "boolean"
  60. },
  61. {
  62. name: "Mode",
  63. type: "argSelector",
  64. "value": [
  65. {
  66. name: "Send",
  67. on: [4],
  68. off: [5]
  69. },
  70. {
  71. name: "Receive",
  72. off: [4],
  73. on: [5]
  74. }
  75. ]
  76. },
  77. {
  78. name: "Input Type",
  79. type: "option",
  80. "value": ["Plaintext", "ITA2"]
  81. },
  82. {
  83. name: "Output Type",
  84. type: "option",
  85. "value": ["Plaintext", "ITA2"]
  86. },
  87. {
  88. name: "ITA2 Format",
  89. type: "option",
  90. "value": ["5/8/9", "+/-/."]
  91. },
  92. {
  93. name: "Ψ1 start (1-43)",
  94. type: "number",
  95. "value": 1
  96. },
  97. {
  98. name: "Ψ2 start (1-47)",
  99. type: "number",
  100. "value": 1
  101. },
  102. {
  103. name: "Ψ3 start (1-51)",
  104. type: "number",
  105. "value": 1
  106. },
  107. {
  108. name: "Ψ4 start (1-53)",
  109. type: "number",
  110. "value": 1
  111. },
  112. {
  113. name: "Ψ5 start (1-59)",
  114. type: "number",
  115. "value": 1
  116. },
  117. {
  118. name: "Μ37 start (1-37)",
  119. type: "number",
  120. "value": 1
  121. },
  122. {
  123. name: "Μ61 start (1-61)",
  124. type: "number",
  125. "value": 1
  126. },
  127. {
  128. name: "Χ1 start (1-41)",
  129. type: "number",
  130. "value": 1
  131. },
  132. {
  133. name: "Χ2 start (1-31)",
  134. type: "number",
  135. "value": 1
  136. },
  137. {
  138. name: "Χ3 start (1-29)",
  139. type: "number",
  140. "value": 1
  141. },
  142. {
  143. name: "Χ4 start (1-26)",
  144. type: "number",
  145. "value": 1
  146. },
  147. {
  148. name: "Χ5 start (1-23)",
  149. type: "number",
  150. "value": 1
  151. },
  152. {
  153. name: "Ψ1 lugs (43)",
  154. type: "string",
  155. value: ".x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x"
  156. },
  157. {
  158. name: "Ψ2 lugs (47)",
  159. type: "string",
  160. value: ".xx.x.xxx..x.x.x..x.xx.x.xxx.x....x.xx.x.x.x..x"
  161. },
  162. {
  163. name: "Ψ3 lugs (51)",
  164. type: "string",
  165. value: ".x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x"
  166. },
  167. {
  168. name: "Ψ4 lugs (53)",
  169. type: "string",
  170. value: ".xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x."
  171. },
  172. {
  173. name: "Ψ5 lugs (59)",
  174. type: "string",
  175. value: "xx...xx.x..x.xx.x...x.x.x.x.x.x.x.x.xx..xxxx.x.x...xx.x..x."
  176. },
  177. {
  178. name: "Μ37 lugs (37)",
  179. type: "string",
  180. value: "x.x.x.x.x.x...x.x.x...x.x.x...x.x...."
  181. },
  182. {
  183. name: "Μ61 lugs (61)",
  184. type: "string",
  185. value: ".xxxx.xxxx.xxx.xxxx.xx....xxx.xxxx.xxxx.xxxx.xxxx.xxx.xxxx..."
  186. },
  187. {
  188. name: "Χ1 lugs (41)",
  189. type: "string",
  190. value: ".x...xxx.x.xxxx.x...x.x..xxx....xx.xxxx.."
  191. },
  192. {
  193. name: "Χ2 lugs (31)",
  194. type: "string",
  195. value: "x..xxx...x.xxxx..xx..x..xx.xx.."
  196. },
  197. {
  198. name: "Χ3 lugs (29)",
  199. type: "string",
  200. value: "..xx..x.xxx...xx...xx..xx.xx."
  201. },
  202. {
  203. name: "Χ4 lugs (26)",
  204. type: "string",
  205. value: "xx..x..xxxx..xx.xxx....x.."
  206. },
  207. {
  208. name: "Χ5 lugs (23)",
  209. type: "string",
  210. value: "xx..xx....xxxx.x..x.x.."
  211. }
  212. ];
  213. }
  214. /**
  215. * @param {string} input
  216. * @param {Object[]} args
  217. * @returns {string}
  218. */
  219. run(input, args) {
  220. const model = args[0],
  221. pattern = args[1],
  222. kt = args[2],
  223. mode = args[3],
  224. format = args[6];
  225. let intype = args[4],
  226. outtype = args[5],
  227. s1 = args[7],
  228. s2 = args[8],
  229. s3 = args[9],
  230. s4 = args[10],
  231. s5 = args[11],
  232. m37 = args[12],
  233. m61 = args[13],
  234. x1 = args[14],
  235. x2 = args[15],
  236. x3 = args[16],
  237. x4 = args[17],
  238. x5 = args[18],
  239. lugs1 = args[19],
  240. lugs2 = args[20],
  241. lugs3 = args[21],
  242. lugs4 = args[22],
  243. lugs5 = args[23],
  244. lugm37 = args[24],
  245. lugm61 = args[25],
  246. lugx1 = args[26],
  247. lugx2 = args[27],
  248. lugx3 = args[28],
  249. lugx4 = args[29],
  250. lugx5 = args[30],
  251. figShifted = false;
  252. this.reverseTable();
  253. if (s1<1 || s1>43) throw new OperationError("Ψ1 start must be between 1 and 43");
  254. if (s2<1 || s2>47) throw new OperationError("Ψ2 start must be between 1 and 47");
  255. if (s3<1 || s3>51) throw new OperationError("Ψ3 start must be between 1 and 51");
  256. if (s4<1 || s4>53) throw new OperationError("Ψ4 start must be between 1 and 53");
  257. if (s5<1 || s5>59) throw new OperationError("Ψ5 start must be between 1 and 59");
  258. if (m37<1 || m37>37) throw new OperationError("Μ37 start must be between 1 and 37");
  259. if (m61<1 || m61>61) throw new OperationError("Μ61 start must be between 1 and 61");
  260. if (x1<1 || x1>41) throw new OperationError("Χ1 start must be between 1 and 41");
  261. if (x2<1 || x2>31) throw new OperationError("Χ2 start must be between 1 and 31");
  262. if (x3<1 || x3>29) throw new OperationError("Χ3 start must be between 1 and 29");
  263. if (x4<1 || x4>26) throw new OperationError("Χ4 start must be between 1 and 26");
  264. if (x5<1 || x5>23) throw new OperationError("Χ5 start must be between 1 and 23");
  265. // Initialise chosen wheel pattern
  266. let chosenSetting = '';
  267. if (pattern === "Custom") {
  268. let re = new RegExp("^[.xX]*$");
  269. if (lugs1.length !== 43 || !re.test(lugs1)) throw new OperationError("Ψ1 custom lugs must be 43 long and can only include . or x ");
  270. if (lugs2.length !== 47 || !re.test(lugs2)) throw new OperationError("Ψ2 custom lugs must be 47 long and can only include . or x");
  271. if (lugs3.length !== 51 || !re.test(lugs3)) throw new OperationError("Ψ3 custom lugs must be 51 long and can only include . or x");
  272. if (lugs4.length !== 53 || !re.test(lugs4)) throw new OperationError("Ψ4 custom lugs must be 53 long and can only include . or x");
  273. if (lugs5.length !== 59 || !re.test(lugs5)) throw new OperationError("Ψ5 custom lugs must be 59 long and can only include . or x");
  274. if (lugm37.length !== 37 || !re.test(lugm37)) throw new OperationError("M37 custom lugs must be 37 long and can only include . or x");
  275. if (lugm61.length !== 61 || !re.test(lugm61)) throw new OperationError("M61 custom lugs must be 61 long and can only include . or x");
  276. if (lugx1.length !== 41 || !re.test(lugx1)) throw new OperationError("Χ1 custom lugs must be 41 long and can only include . or x");
  277. if (lugx2.length !== 31 || !re.test(lugx2)) throw new OperationError("Χ2 custom lugs must be 31 long and can only include . or x");
  278. if (lugx3.length !== 29 || !re.test(lugx3)) throw new OperationError("Χ3 custom lugs must be 29 long and can only include . or x");
  279. if (lugx4.length !== 26 || !re.test(lugx4)) throw new OperationError("Χ4 custom lugs must be 26 long and can only include . or x");
  280. if (lugx5.length !== 23 || !re.test(lugx5)) throw new OperationError("Χ5 custom lugs must be 23 long and can only include . or x");
  281. chosenSetting = INIT_PATTERNS["No Pattern"];
  282. chosenSetting.S[1] = this.readLugs(lugs1);
  283. chosenSetting.S[2] = this.readLugs(lugs2);
  284. chosenSetting.S[3] = this.readLugs(lugs3);
  285. chosenSetting.S[4] = this.readLugs(lugs4);
  286. chosenSetting.S[5] = this.readLugs(lugs5);
  287. chosenSetting.M[1] = this.readLugs(lugm37);
  288. chosenSetting.M[2] = this.readLugs(lugm61);
  289. chosenSetting.X[1] = this.readLugs(lugx1);
  290. chosenSetting.X[2] = this.readLugs(lugx2);
  291. chosenSetting.X[3] = this.readLugs(lugx3);
  292. chosenSetting.X[4] = this.readLugs(lugx4);
  293. chosenSetting.X[5] = this.readLugs(lugx5);
  294. } else {
  295. chosenSetting = INIT_PATTERNS[pattern];
  296. }
  297. var chiSettings = chosenSetting.X; // Pin settings for Chi links (X)
  298. var psiSettings = chosenSetting.S; // Pin settings for Psi links (S)
  299. var muSettings = chosenSetting.M; // Pin settings for Motor links (M)
  300. let ita2 = "";
  301. if (mode === "Send") {
  302. // Convert input text to ITA2 (including figure/letter shifts)
  303. ita2 = Array.prototype.map.call(input, function(character) {
  304. let letter = character.toUpperCase();
  305. if (intype === "Plaintext") {
  306. if (validChars.indexOf(letter) === -1) throw new OperationError("Invalid Plaintext character : "+letter);
  307. if(!figShifted && figShiftedChars.indexOf(letter) !== -1) {
  308. // in letters mode and next char needs to be figure shifted
  309. figShifted = true;
  310. return "55" + figShiftArr[letter];
  311. } else if (figShifted) {
  312. // in figures mode and next char needs to be letter shifted
  313. if (letter==="\n") return "34";
  314. if (letter==="\r") return "4";
  315. if (figShiftedChars.indexOf(letter) === -1) {
  316. figShifted = false;
  317. return "88" + letter;
  318. } else {
  319. return figShiftArr[letter];
  320. }
  321. } else {
  322. if (letter==="\n") return "34";
  323. if (letter==="\r") return "4";
  324. return letter;
  325. }
  326. } else {
  327. if (validITA2.indexOf(letter) === -1) {
  328. let errltr = letter;
  329. if (errltr==="\n") errltr = "Carriage Return";
  330. if (errltr===" ") errltr = "Space";
  331. throw new OperationError("Invalid ITA2 character : "+errltr);
  332. }
  333. return letter;
  334. }
  335. });
  336. } else {
  337. // Receive input should always be ITA2
  338. ita2 = Array.prototype.map.call(input, function(character) {
  339. let letter = character.toUpperCase();
  340. if (validITA2.indexOf(letter) === -1) {
  341. var errltr = letter;
  342. if (errltr==="\n") errltr = "Carriage Return";
  343. if(errltr===" ") errltr = "Space";
  344. throw new OperationError("Invalid ITA2 character : "+errltr);
  345. }
  346. return letter;
  347. });
  348. }
  349. const ita2Input = ita2.join("");
  350. let thisPsi = [];
  351. let thisChi = [];
  352. let m61lug = muSettings[1][m61-1];
  353. let m37lug = muSettings[2][m37-1];
  354. let p5 = [0,0,0];
  355. const self = this;
  356. const letters = Array.prototype.map.call(ita2Input, function(character) {
  357. const letter = character.toUpperCase();
  358. let x2bptr = x2+1;
  359. if (x2bptr===32) x2bptr=1;
  360. let s1bptr = s1+1;
  361. if (s1bptr===44) s1bptr=1;
  362. thisChi = [
  363. chiSettings[1][x1-1],
  364. chiSettings[2][x2-1],
  365. chiSettings[3][x3-1],
  366. chiSettings[4][x4-1],
  367. chiSettings[5][x5-1]
  368. ];
  369. thisPsi = [
  370. psiSettings[1][s1-1],
  371. psiSettings[2][s2-1],
  372. psiSettings[3][s3-1],
  373. psiSettings[4][s4-1],
  374. psiSettings[5][s5-1]
  375. ];
  376. if (typeof ITA2_TABLE[letter] == "undefined") {
  377. return "";
  378. }
  379. let xorSum = [];
  380. for(var i=0;i<=4;i++) {
  381. xorSum[i] = ITA2_TABLE[letter][i] ^ thisPsi[i] ^ thisChi[i];
  382. }
  383. const resultStr = xorSum.join("");
  384. // Move Chi wheels one back after each letter
  385. if (--x1 < 1) x1 = 41;
  386. if (--x2 < 1) x2 = 31;
  387. if (--x3 < 1) x3 = 29;
  388. if (--x4 < 1) x4 = 26;
  389. if (--x5 < 1) x5 = 23;
  390. // Motor wheel (61 pin) also moves one each letter
  391. if (--m61 < 1) m61 = 61;
  392. // If M61 is set, we also move M37
  393. if (m61lug === 1) {
  394. if (--m37 < 1) m37 = 37;
  395. }
  396. let basicmotor = m37lug;
  397. let totalmotor = basicmotor;
  398. let lim = 0;
  399. p5[2] = p5[1];
  400. p5[1] = p5[0];
  401. if (mode==="Send") {
  402. p5[0] = ITA2_TABLE[letter][4];
  403. } else {
  404. p5[0] = xorSum[4];
  405. }
  406. // Limitations here
  407. if (model==='SZ42a') {
  408. // Chi 2 one back lim - The active character of chi 2 (2nd Chi wheel) in the previous position
  409. lim = chiSettings[2][x2bptr-1];
  410. if(kt) {
  411. if (lim===p5[2]) { lim = 0; } else { lim=1; } //p5 back 2
  412. }
  413. // If basic motor = 0 and limitation = 1, Total motor = 0 [no move], otherwise, total motor = 1 [move]
  414. if (basicmotor===0 && lim===1) {
  415. totalmotor = 0;
  416. } else {
  417. totalmotor = 1;
  418. }
  419. } else if(model=='SZ42b') {
  420. // Chi 2 one back + Psi 1 one back.
  421. const x2b1lug = chiSettings[2][x2bptr-1];
  422. const s1b1lug = psiSettings[1][s1bptr-1];
  423. lim = 1;
  424. if (x2b1lug===s1b1lug) lim=0;
  425. if(kt) {
  426. if (lim===p5[2]) { lim=0; } else { lim=1; } //p5 back 2
  427. }
  428. // If basic motor = 0 and limitation = 1, Total motor = 0 [no move], otherwise, total motor = 1 [move]
  429. if (basicmotor===0 && lim===1) {
  430. totalmotor = 0;
  431. } else {
  432. totalmotor = 1;
  433. }
  434. } else if (model==="SZ40") {
  435. // SZ40
  436. totalmotor = basicmotor;
  437. } else {
  438. throw new OperationError("Lorenz model type not recognised");
  439. }
  440. // increment Psi wheels when current totalmotor active
  441. if (totalmotor === 1) {
  442. if(--s1 < 1) s1 = 43;
  443. if(--s2 < 1) s2 = 47;
  444. if(--s3 < 1) s3 = 51;
  445. if(--s4 < 1) s4 = 53;
  446. if(--s5 < 1) s5 = 59;
  447. }
  448. m61lug = muSettings[1][m61-1];
  449. m37lug = muSettings[2][m37-1];
  450. let rtnstr = self.REVERSE_ITA2_TABLE[resultStr];
  451. if (format==="5/8/9") {
  452. if (rtnstr==="+") rtnstr="5";
  453. if (rtnstr==="-") rtnstr="8";
  454. if (rtnstr===".") rtnstr="9";
  455. }
  456. return rtnstr;
  457. });
  458. let ita2output = letters.join("");
  459. let output = "";
  460. if (mode === "Receive") {
  461. figShifted = false;
  462. // Convert output ITA2 to plaintext (including figure/letter shifts)
  463. const out = Array.prototype.map.call(ita2output, function(letter) {
  464. if (outtype === "Plaintext") {
  465. if (letter === "5" || letter === "+") {
  466. figShifted = true;
  467. return;
  468. } else if (letter === "8" || letter === "-") {
  469. figShifted = false;
  470. return;
  471. } else if (letter === "9") {
  472. return " ";
  473. } else if (letter === "3") {
  474. return "\n";
  475. } else if (letter === "4") {
  476. return "";
  477. }
  478. if (figShifted) {
  479. return self.REVERSE_FIGSHIFT_TABLE[letter];
  480. } else {
  481. return letter;
  482. }
  483. } else {
  484. return letter;
  485. }
  486. });
  487. output = out.join("");
  488. } else {
  489. output = ita2output;
  490. }
  491. return output;
  492. }
  493. /**
  494. * Reverses the ITA2 Code lookup table
  495. */
  496. reverseTable() {
  497. this.REVERSE_ITA2_TABLE = {};
  498. this.REVERSE_FIGSHIFT_TABLE = {};
  499. for (const letter in ITA2_TABLE) {
  500. const code = ITA2_TABLE[letter];
  501. this.REVERSE_ITA2_TABLE[code] = letter;
  502. }
  503. for (const letter in figShiftArr) {
  504. const ltr = figShiftArr[letter];
  505. this.REVERSE_FIGSHIFT_TABLE[ltr] = letter;
  506. }
  507. }
  508. readLugs(lugstr) {
  509. let arr = Array.prototype.map.call(lugstr, function(lug) {
  510. if(lug==".") {
  511. return 0;
  512. } else {
  513. return 1;
  514. }
  515. });
  516. return arr;
  517. }
  518. }
  519. const ITA2_TABLE = {
  520. "A": "11000",
  521. "B": "10011",
  522. "C": "01110",
  523. "D": "10010",
  524. "E": "10000",
  525. "F": "10110",
  526. "G": "01011",
  527. "H": "00101",
  528. "I": "01100",
  529. "J": "11010",
  530. "K": "11110",
  531. "L": "01001",
  532. "M": "00111",
  533. "N": "00110",
  534. "O": "00011",
  535. "P": "01101",
  536. "Q": "11101",
  537. "R": "01010",
  538. "S": "10100",
  539. "T": "00001",
  540. "U": "11100",
  541. "V": "01111",
  542. "W": "11001",
  543. "X": "10111",
  544. "Y": "10101",
  545. "Z": "10001",
  546. "3": "00010",
  547. "4": "01000",
  548. "9": "00100",
  549. "/": "00000",
  550. " ": "00100",
  551. ".": "00100",
  552. "8": "11111",
  553. "5": "11011",
  554. "-": "11111",
  555. "+": "11011"
  556. };
  557. const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-'()/:=?,. \n\r";
  558. const validITA2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ34589+-./";
  559. const figShiftedChars = "1234567890+-'()/:=?,."
  560. const figShiftArr = {
  561. "1": "Q",
  562. "2": "W",
  563. "3": "E",
  564. "4": "R",
  565. "5": "T",
  566. "6": "Y",
  567. "7": "U",
  568. "8": "I",
  569. "9": "O",
  570. "0": "P",
  571. " ": "9",
  572. "-": "A",
  573. "?": "B",
  574. ":": "C",
  575. "#": "D",
  576. "%": "F",
  577. "@": "G",
  578. "£": "H",
  579. "(": "K",
  580. ")": "L",
  581. ".": "M",
  582. ",": "N",
  583. "'": "S",
  584. "=": "V",
  585. "/": "X",
  586. "+": "Z",
  587. "\n": "3",
  588. "\r": "4"
  589. };
  590. const INIT_PATTERNS = {
  591. "No Pattern": {
  592. "X": {
  593. 1: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  594. 2: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  595. 3: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  596. 4: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  597. 5: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  598. },
  599. "S": {
  600. 1: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  601. 2: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  602. 3: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  603. 4: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  604. 5: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  605. },
  606. "M": {
  607. 1: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  608. 2: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
  609. }
  610. },
  611. "KH Pattern": {
  612. "X": {
  613. 1: [0,1,0,0,0,1,1,1,0,1,0,1,1,1,1,0,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,1,1,0,1,1,1,1,0,0],
  614. 2: [1,0,0,1,1,1,0,0,0,1,0,1,1,1,1,0,0,1,1,0,0,1,0,0,1,1,0,1,1,0,0],
  615. 3: [0,0,1,1,0,0,1,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,1,1,0],
  616. 4: [1,1,0,0,1,0,0,1,1,1,1,0,0,1,1,0,1,1,1,0,0,0,0,1,0,0],
  617. 5: [1,1,0,0,1,1,0,0,0,0,1,1,1,1,0,1,0,0,1,0,1,0,0]
  618. },
  619. "S": {
  620. 1: [0,1,0,0,0,1,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,1],
  621. 2: [0,1,1,0,1,0,1,1,1,0,0,1,0,1,0,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1,0,0,0,0,1,0,1,1,0,1,0,1,0,1,0,0,1],
  622. 3: [0,1,0,1,0,1,0,0,1,1,1,0,0,0,0,1,0,1,0,1,1,0,1,0,1,0,1,0,0,1,1,1,0,1,0,1,0,0,1,0,1,0,1,1,0,0,1,0,1,0,1],
  623. 4: [0,1,1,0,0,0,1,1,1,1,1,0,1,0,1,0,1,1,0,0,0,1,0,1,1,0,1,0,1,0,0,1,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0],
  624. 5: [1,1,0,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,1,0,0,0,1,1,0,1,0,0,1,0]
  625. },
  626. "M": {
  627. 1: [0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,0,0,0],
  628. 2: [1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,1,0,0,0,0]
  629. }
  630. },
  631. "ZMUG Pattern": {
  632. "X": {
  633. 1: [0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1,1,1,0,0,0,0,1,1,1,0,0,1,1,0],
  634. 2: [1,1,0,1,1,0,0,0,0,1,1,1,0,1,1,1,1,0,1,0,0,0,1,1,0,0,1,1,0,0,0],
  635. 3: [0,0,1,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,1,1,0,1,1,1,1,0],
  636. 4: [1,0,1,0,1,0,0,1,1,0,0,0,1,1,0,0,1,0,1,1,1,0,0,1,0,1],
  637. 5: [0,1,0,0,1,1,1,1,0,0,0,1,0,1,1,1,0,0,0,0,1,0,1]
  638. },
  639. "S": {
  640. 1: [1,1,0,1,0,0,1,1,0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,0,0,1,1,1,0,0,1,1,1,0,0,0],
  641. 2: [0,0,0,1,0,0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,1,1,0,0,1,0,1,1],
  642. 3: [0,1,0,0,1,1,0,0,1,1,1,0,0,1,1,1,0,0,1,0,0,0,1,1,1,1,0,0,0,1,0,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,1,1,1],
  643. 4: [0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0,1,1,1,1,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0,0,1,0,0,1,1,0,0,0,1,1,0,0,1,1,1,0,1],
  644. 5: [1,0,0,1,1,1,0,0,0,1,0,0,0,1,1,1,1,0,0,1,1,1,0,0,1,0,0,1,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0,1,0,0,0,1,1,0]
  645. },
  646. "M": {
  647. 1: [1,0,1,1,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,0,1,0,1,1,1,1,0,1,0,1,0,1],
  648. 2: [0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,1,0,1,1,1,0,1,1,1,0,1,1,1]
  649. }
  650. },
  651. "BREAM Pattern": {
  652. "X": {
  653. 1: [0,1,1,1,1,0,1,0,1,1,0,1,0,1,1,0,0,1,0,0,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,1,1,1,0,0,0],
  654. 2: [0,1,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,1,1,0,1,1,1,0,0,1,1],
  655. 3: [1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,1,0,0,1,1,0,1,1,1,0,0],
  656. 4: [1,1,1,1,0,0,1,0,0,1,1,0,0,1,0,0,1,1,0,1,0,0,1,1,0,0],
  657. 5: [0,1,1,1,0,1,1,1,0,0,0,1,0,0,1,1,0,1,0,0,0,1,0]
  658. },
  659. "S": {
  660. 1: [0,0,0,1,1,1,0,0,1,1,1,0,1,1,0,0,1,0,1,0,1,1,0,1,1,0,1,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0],
  661. 2: [1,1,0,1,0,0,1,1,1,0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,0,0],
  662. 3: [1,0,0,1,0,0,1,1,0,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,1,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1],
  663. 4: [0,1,0,0,0,0,1,0,0,1,0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1],
  664. 5: [1,0,1,0,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,1,0,1,1,1,1,0,1,1,1,0,0,1,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0]
  665. },
  666. "M": {
  667. 1: [1,0,0,0,0,1,1,0,0,0,1,1,0,0,1,1,0,1,1,1,1,0,0,0,0,1,1,0,0,0,1,1,0,1,1,0,1,0,1,1,1,1,0,0,0,1,1,0,0,1,1,0,0,1,1,0,1,0,1,1,1],
  668. 2: [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,0,1]
  669. }
  670. }
  671. };
  672. export default Lorenz;