2019-03-02 15:00:42 +01:00
/ * *
2019-09-04 18:13:05 +02:00
* @ author Karsten Silkenbäumer [ github . com / kassi ]
* @ copyright Karsten Silkenbäumer 2019
* @ license Apache - 2.0
* /
2019-03-02 15:00:42 +01:00
2019-11-06 14:01:52 +01:00
import Operation from "../Operation.mjs" ;
2019-03-02 15:00:42 +01:00
import {
2019-03-02 17:55:03 +01:00
BACON _ALPHABETS ,
2019-03-02 17:33:17 +01:00
BACON _TRANSLATION _CASE , BACON _TRANSLATION _AMNZ , BACON _TRANSLATIONS , BACON _CLEARER _MAP , BACON _NORMALIZE _MAP ,
swapZeroAndOne
2019-11-06 14:01:52 +01:00
} from "../lib/Bacon.mjs" ;
2019-03-02 15:00:42 +01:00
/ * *
2019-09-04 18:13:05 +02:00
* Bacon Cipher Decode operation
* /
2019-03-02 15:00:42 +01:00
class BaconCipherDecode extends Operation {
/ * *
2019-09-04 18:13:05 +02:00
* BaconCipherDecode constructor
* /
2019-03-02 15:00:42 +01:00
constructor ( ) {
super ( ) ;
this . name = "Bacon Cipher Decode" ;
this . module = "Default" ;
2019-09-04 18:13:05 +02:00
this . description = "Bacon's cipher or the Baconian cipher is a method of steganography devised by Francis Bacon in 1605. A message is concealed in the presentation of text, rather than its content." ;
this . infoURL = "https://wikipedia.org/wiki/Bacon%27s_cipher" ;
2019-03-02 15:00:42 +01:00
this . inputType = "string" ;
this . outputType = "string" ;
this . args = [
{
"name" : "Alphabet" ,
"type" : "option" ,
2019-03-02 17:55:03 +01:00
"value" : Object . keys ( BACON _ALPHABETS )
2019-03-02 15:00:42 +01:00
} ,
{
"name" : "Translation" ,
"type" : "option" ,
"value" : BACON _TRANSLATIONS
} ,
{
"name" : "Invert Translation" ,
"type" : "boolean" ,
"value" : false
}
] ;
2020-03-24 12:06:37 +01:00
this . checks = [
{
pattern : "^\\s*([01]{5}\\s?)+$" ,
flags : "" ,
args : [ "Standard (I=J and U=V)" , "0/1" , false ]
} ,
{
pattern : "^\\s*([01]{5}\\s?)+$" ,
flags : "" ,
args : [ "Standard (I=J and U=V)" , "0/1" , true ]
} ,
{
pattern : "^\\s*([AB]{5}\\s?)+$" ,
flags : "" ,
args : [ "Standard (I=J and U=V)" , "A/B" , false ]
} ,
{
pattern : "^\\s*([AB]{5}\\s?)+$" ,
flags : "" ,
args : [ "Standard (I=J and U=V)" , "A/B" , true ]
} ,
{
pattern : "^\\s*([01]{5}\\s?)+$" ,
flags : "" ,
args : [ "Complete" , "0/1" , false ]
} ,
{
pattern : "^\\s*([01]{5}\\s?)+$" ,
flags : "" ,
args : [ "Complete" , "0/1" , true ]
} ,
{
pattern : "^\\s*([AB]{5}\\s?)+$" ,
flags : "" ,
args : [ "Complete" , "A/B" , false ]
} ,
{
pattern : "^\\s*([AB]{5}\\s?)+$" ,
flags : "" ,
args : [ "Complete" , "A/B" , true ]
2020-02-25 12:27:03 +01:00
}
2020-03-24 12:06:37 +01:00
] ;
2019-03-02 15:00:42 +01:00
}
/ * *
2019-09-04 18:13:05 +02:00
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { string }
* /
2019-03-02 15:00:42 +01:00
run ( input , args ) {
const [ alphabet , translation , invert ] = args ;
2019-03-02 17:55:03 +01:00
const alphabetObject = BACON _ALPHABETS [ alphabet ] ;
2019-03-02 15:00:42 +01:00
// remove invalid characters
input = input . replace ( BACON _CLEARER _MAP [ translation ] , "" ) ;
2019-03-02 17:55:03 +01:00
2019-03-02 15:00:42 +01:00
// normalize to unique alphabet
if ( BACON _NORMALIZE _MAP [ translation ] !== undefined ) {
input = input . replace ( /./g , function ( c ) {
return BACON _NORMALIZE _MAP [ translation ] [ c ] ;
} ) ;
} else if ( translation === BACON _TRANSLATION _CASE ) {
const codeA = "A" . charCodeAt ( 0 ) ;
const codeZ = "Z" . charCodeAt ( 0 ) ;
input = input . replace ( /./g , function ( c ) {
const code = c . charCodeAt ( 0 ) ;
if ( code >= codeA && code <= codeZ ) {
return "1" ;
} else {
return "0" ;
}
} ) ;
} else if ( translation === BACON _TRANSLATION _AMNZ ) {
2019-03-02 22:17:44 +01:00
const words = input . split ( /\s+/ ) ;
2019-03-02 15:00:42 +01:00
const letters = words . map ( function ( e ) {
2019-03-02 22:17:44 +01:00
if ( e ) {
const code = e [ 0 ] . toUpperCase ( ) . charCodeAt ( 0 ) ;
return code >= "N" . charCodeAt ( 0 ) ? "1" : "0" ;
} else {
return "" ;
}
2019-03-02 15:00:42 +01:00
} ) ;
input = letters . join ( "" ) ;
}
if ( invert ) {
2019-03-02 17:33:17 +01:00
input = swapZeroAndOne ( input ) ;
2019-03-02 15:00:42 +01:00
}
// group into 5
const inputArray = input . match ( /(.{5})/g ) || [ ] ;
let output = "" ;
2019-09-04 18:13:05 +02:00
for ( let i = 0 ; i < inputArray . length ; i ++ ) {
const code = inputArray [ i ] ;
2019-03-02 15:00:42 +01:00
const number = parseInt ( code , 2 ) ;
2019-03-02 17:55:03 +01:00
output += number < alphabetObject . alphabet . length ? alphabetObject . alphabet [ number ] : "?" ;
2019-03-02 15:00:42 +01:00
}
return output ;
}
}
export default BaconCipherDecode ;