type node = N of node list | S of string | R of node array | Many of node * int * string | P | O of node | Filter of (string->string) * node;;
let gclass = R[|S"Warrior"; S "Bard"; S "Ranger"; S "Wizard"; S "Mage"; S "Paladin"; S "Rogue"; S "Ninja"; S "Warlock"; S "Champion"; S "Barbarian"; S "Assassin"; S "Conjurer"; S "Summoner"; S "Fighter"; S "Berserker"; S "Druid"; S "Orc"; S "Goblin"|]
let name = R [|
	S "Stalin"; S "Hitler"; S "Marx"; S "Kony"; S "Mao"; S "Mussolini"; S "Trump"; S "Ted Cruz"; S "esr"; S "Richard Dawkins"; S "Mishima"; S "Nixon"; S "Kissinger"; S "Reagan"; S "Erdogan"; S "Hillary"; S "Clinton"; S "Bernie"; S "Sanders"; S "David Cameron"; S "Thatcher"; S "Nigel Farage"; S "McCarthy"; S "Putin"; S "Frank Underwood"; S "Andrew Jackson"; S "Sam Harris"; S "Christopher Hitchens"; S "Columbus"; S "Julian Assange"; S "Marcus Cicero"; S "Caligula"; S "Nero"; S "Commodus"; S "Caracalla"; S "Constantine"; S "Atilla the Hun"; S "Glenn Greenwald"; S "Ed Balls"; S "Edward Snowden"; S "Genghis Khan";
|]
let nomen = R [| S"nationalist"; S "capitalist"; S "Libertarian"; S "atheist"; S "conservative"; S "Marxist"; S "beta"; S "rationalist"; S "Republican"; S "Neoreactionary"; S "communist"; S "moe"; S "NRx"; S "racial realist"; S "hacktivist"; S "European"; S "European-American"; S "white separatist"; S "Anonymous"; S "heterosexual"; S "intellectual"; S "moderate"; S "sapiosexual"; S "intellectual"; S "egalitarian";|]
let adj = R [|nomen; S "circumgender"; S "transracial"; S "free-thinking"; S "incel"; S "proud"; S "rational"; S "straight"; S "opinionated"; S "politically active"; S "traditional"; S "pro-life"; S "angry"; S "white"|]
let band = R[|S"Metallica"; S "Nine Inch Nails"; S "Taylor Swift"; S "Drake"; S "Run The Jewels"; S "Daft Punk"; S "Amanda Palmer"; S "Coldplay"; S "Radiohead";|]
let trendy_food = R [| S "bacon"; S "vodka"; S "beer"; S "wine"; S "coffee"; S "whiskey"; S "Soylent"; S "steak"; S "kale"; |]
let lang = R [| S "Ruby"; S "Rails"; S "Python"; S "Scala"; S "Java"; S "PHP"; S "Haskell"; S "LISP"; S "JavaScript"; S "node.js"; S "React"; S "Backbone"; S "Polymer"; S "Ember"; S "Angular"; S ".NET"; S "C#"; S "F#"; S "Visual Basic .NET"; S "PowerShell"; S "Meteor.js"; S "jQuery"; S "Linux"; S "GNU/Linux"; S "UNIX"; S "AWK"; S "bash"; S "zsh"; S "fish"; S "GNU"; S "Open Source "; S "Erlang"; S "Docker"; S "R"; S "Hadoop"; S "Android"; S "iOS"; S "Unity"; S "Unreal Engine"; S "UE4"; S "Source Engine"; S "Apache"; S "Lua"; S "Prolog"; S "C++"; S "D"; S "Go"; S "Golang"; S "Rust"; S "Nim"; S "OCaml"; S "Kotlin"; S "Clojure"; S "Groovy"; S "Scheme"; S "Common Lisp"; S "llvm"; S "LLVM"; S "Hoon"; S "Urbit"; S "Nock"; S "Elixir"; S "Crystal"; S "TypeScript"; S "PureScript"; S "CoffeeScript"; S "Elm"; S "LaTeX"; S "troff"; S "groff"; S "Markdown"; S "HTML"; S "CSS"; S "XSLT"; S "Flash"; S "ColdFusion"; S "FORTRAN"; S "COBOL"; S "Matlab"; S "Mathematica"; S "CUDA"; S "OpenCL"; S "OpenGL"; S "DirectX"; S "Vulkan"; S "Pascal"; S "Perl"; S "Perl 6"; S "UX"; S "Emacs Lisp"; S "Vimscript"; S "AppleScript"; S "Swift"; S "Objective-C"; S "Cocoa"; S "Cocoa Touch"; S "Xamarin"; S "Qt"; S "GTK+"; S "WPF"; S "JavaFX"; S "Swing"; S "Smalltalk" |]
let dev = R[|N[lang; S " developer";];  N[lang; S " evangelist";]; N[lang; S " dev";]; N[lang; S " lover";]; N[lang; S " enthusiast";]; N[lang; S " professional";]; N[lang; S " expert";]; N[lang; S " "; gclass]; N[lang; S " connoisseur";];|]
let rec activity = R [|band; trendy_food; S"freedom"; S "free speech"; S"nationalism"; S "Minecraft"; S "Call of Duty"; S "partying"; S "beer pong"; S "football"; S "baseball"; S "vaping"; S "pussy"; S "bacon"; S "LessWrong"; S "America"; S "RationalWiki"; S "memes"; S "4chan"; S "8chan"; S "comics"; S "hacktivism"; S "hacking"; S "ComicCon"; S "cosplay"; S "Game of Thrones"; S "hentai"; S "advocacy"; N[noun; S " advocacy";]; S "sex"; S "science"; S "anime"; S "Big Data"; S "Cloud"; S "butts"; S "UKIP"; S "white separatism"; S "Brexit"; S "grammar"; S "free software"; S "open source"; S "real literature";|]
and noun = R [|
	nomen; S "Christian"; S "brony"; S "bro"; S "brogrammer"; S "brocialist"; N[activity; S "evangelist"]; N [S "bro"; noun]; dev; N[S "10x "; lang; S " dev";]; S "free-thinker"; S "Redditor"; S "atheist"; S "furry"; S "victim of cisphobia"; S "male feminist"; S "equalist"; S "MRA"; S "beer drinker"; S "father"; S "blogger"; N[noun; S "blogger";]; S "Thatcherite"; S "geek"; S "thought leader"; S "antivax"; S "channer"; S "Men's Rights Activist"; N[S "Social Justice "; gclass]; N[activity; S "lover";]; S "Anonymous"; S "infosec professional"; S "BernieBro"; S "Marxist"; S "socialist"; S "journalist"; S "marketer"; S "social media analyst"; S "philosopher"; S "educator"; S "advocate"; N[activity; S " advocate"]; S "sexpert"; S "professional"; N[activity; S" expert";]; N[activity; S"ninja";]; S "Pythonista"; S "Rubyist"; S "PhD candidate"; S "cartoonist"; S "man"; S "skeptic"; S "grammar Nazi"; S "open sorcerer"; S "podcaster"; N[name; S "-wannabe"]; S "lover"; S "detective"; S "trekkie"; S "fuckboy"; S "Soylent eater";
|]
let political_party = R[|
S "Green"; S "Labour"; S "Labor"; S "National"; S "Libertarian"; S "Democratic"; S "Republican"; S "Liberal Democrat"; S "Lib Dem"; S "Tory"; S "Conservative"; S "Liberal"; S "UKIP"; S "BNP"; S "SSP"; S "Britain First"; S "Pirate"; S "Sex"; S "Communist";
|]
let minority = R [| S "gays"; S "homosexuals"; S "jews"; S "Arabs"; S "Mexicans"; S "Muslims"; S "immigrants"; S "blacks"; S "transgendereds"; S "transgenders"; S "transgenderists"; S "queers"; S "SJWs"; S "feminists"; S "indie game developers"; S "gamers"; S "homos"; |];;
let minority_kind = R [|S "gender"; S "justice"; S "trans"; S "feminism"; S "queer"; S "gay"; S "homosexual";|]

let startup = R[|S "Fumblr"; S "Grumblr"; S "Humblr"; S "Appearancely"; S "AccidentNow"; S "RefuseNow"; S "remainr"; S "Trembleit"; S "Punish"; S "SprayNow"; S "Tennisr"; S "Traply"; S "Yawnin"; S "momly"; S "Smartyell"; S "radiatein"; S "sawly"; S "suffery"; S "Sceneify"; S "WomanNow"; S "Ballhub"; S "Systemme"; S "Earnify"; S "Mathit"; S "Gruntly"; S "Bongh.it"; S "Lyly"|];;
let hashtag = R [|
	S "#BlueLivesMatter";
	S "#AllLivesMatter";
	S "#NotAllMen";
	S "#KONY2012";
	S "#GamerGate";
	S "#FeelTheBern";
	S "#ImWithHer";
	S "#BuildTheWall";
	S "#VoteLeave";
	S "#FreeWeev";
	S "#WhiteGenocide";
	S "#2Ad";
	S "#NordicModel";
|]
let verb = R [| S "game"; S "code"; S "blog"; S "hack"; S "vape pussy" |]
let startup_position = R[|S "CEO"; S "CTO"; S "Soylent eater"; S "Dev"; S "$dev"; S "Product Manager"; S "Customer Success Manager"; S "Full Stack Engineer"; S "Data journalist"; S "Infosec Expert"; S "Designer"; S "UX"; S "Hacker"; S "Engineer"; S "VP of Engineering"; S "Data scientist"; S "Growth Hacker"; S "Marketing"; S "Sexpert"|]
let sportsball_team = R[|S "Ducks"; S "Beavers"; S "Steelers"; S "Lakers"; S "Blazers"; S "Redskins"; S "Clippers"; S "All Blacks"; S "Newcastle"; S "Cubs"; S "West Ham"; S "Man U"; S "Chelsea"; S "Liverpool"|]
let activity = R [| band; trendy_food; S "Minecraft"; S "Call of Duty"; S "partying"; S "beer pong"; S "football"; S "baseball"; S "vaping"; S "pussy"; S "bacon"; S "LessWrong"; S "America"; S "RationalWiki"; S "memes"; S "4chan"; S "8chan"; S "comics"; S "hacktivism"; S "hacking"; S "ComicCon"; S "cosplay"; S "Game of Thrones"; S "hentai"; S "advocacy"; N[noun; S " advocacy";]; S "sex"; S "science"; S "anime"; S "Big Data"; S "Cloud"; S "Butts"; S "UKIP"; S "white separatism"; S "Brexit"; S "grammar"; S "free software"; S "open source"; S "real literature"; S "Star Trek"; S "Star Wars"; |]
let rec activity_phrase = N[activity; O(N[S", "; activity_phrase])]

let phrase = R [|
	N[S "Husband, father, "; noun; P;];
	S "Friendly.";
	S "Hubby.";
	S "That is all.";
	S "Not as funny as I think I am.";
	S "Nice guy.";
	S "You have been warned.";
	N[S "Avatar by "; name; S ".";];
	S "Jet fuel can't melt steel beams.";
	N[minority; S " can't melt steel beams.";];
	N[activity; S " can't melt steel beams.";];
	N[lang; S " can't melt steel beams.";];
	N[name; S " was right.";];
	S "Ally.";
	S "Cynical bastard.";
	S "Proud Ally.";
	S "Don't follow if you're easily offended.";
	S "I aim to offend.";
	S "Sarcastic.";
	S "TERF is a slur.";
	S "Put the Christ back in Christmas.";
	S "Give me liberty or give me death.";
	S "Fights for the users.";
	S "I call them like I see them.";
	S "I calls 'em like I sees 'em.";
	S "Honest.";
	S "I fear I am now a victim of 'cisphobia'.";
	N[O(N[Many(adj,1," "); S " "]); noun; P;];
	N[O(N[Many(adj,1," "); S " "]); S "#"; noun; P;];
	N[adj; P;];
	N[Many(adj,3," "); S " #"; noun; S " and proud of it"; P;];
	N[activity_phrase; P];
	S "No fatties.";
	N[minority_kind; S " critical."];
	N[minority_kind; S "-critical."];
	N[minority_kind; S " separatist.";];
	N[S "Go "; sportsball_team; S "!";];
	S "Don't tread on me.";
	S "English only.";
	S "We are all Africans.";
	S "Je suis Charlie.";
	N[S "Je suis "; name; P;];
	N[S "I am "; name; P;];
	N[S "We are all "; name; P];
	N[minority; S " are the real oppressors.";];
	N[minority; S " are the real racists.";];
	N[S "My best friends are "; minority; P;];
	N[S "Lover of all things "; lang; P;];
	N[S "Lover of all things "; activity; P;];
	S "RTs are not endorsements.";
	S "Thoughts are my own.";
	N[S "CEO of "; startup;];
	N[startup_position; S " at "; startup; P; ];
	S "Opinions are my own.";
	S "Opinions do not reflect those of my employer.";
	N[adj; S " pride.";];
	N[noun; S " pride.";];
	N[S "I like "; activity; P;];
	N[S "I stand with "; name; S ".";];
	S "I speak truth to power.";
	S "History will vindicate me.";
	S "Make America great again.";
	N[S "Co-founder of "; startup; P];
	S "Molon labe.";
	S "Μολών λαβέ.";
	S "The best cure for bad speech is more speech.";
	N[S "I "; verb; P;];
	N[S "I "; verb; S " and I vote.";];
	S "My public key: https://keyface.ohno/f897b10a.";
	N[S "Make America "; adj; S " again.";];
	S "Watch my TED Talk.";
	N[minority; S " need not apply.";];
	N[S "((("; name; S ")))";];
	N[S "Fan of "; band; P;];
	S "Beyhive.";
	S "He/him.";
	N[noun; S", "; noun; S ", "; noun; S ", not necessarily in that order.";];
	N[minority; S " are what's wrong with America.";];
	N[minority; S " go home.";];
	N[trendy_food; S " addict.";];
	N[trendy_food; S " enthusiast.";];
	N[trendy_food; S " and "; trendy_food; S ".";];
	N[Many(trendy_food,2,", "); S " and "; trendy_food; S ".";];
	N[trendy_food; S " is what's wrong with America.";];
	S "14/88.";
	S "No trigger warnings.";
	S "Resistance is futile.";
	N[political_party; S " shill.";];
	N[political_party; S " activist.";];
	N[S "Vote "; political_party; S "!";];
	N[name; S " for president!";];
	N[name; S " for America.";];
	S "I love correcting people who are wrong.";
	S "Carthago delenda est.";
	S "Don't @ me.";
	S "Just say no.";
	S "PM me for direct sales.";
	
|];;
let top = N[ Many(Filter(String.capitalize_ascii,phrase),2," "); O(N[S " "; Many(hashtag,1," ")]);]
let range min max = (Random.int (max-min)) + min
let pick (r: 'a array) : 'a = r.(range 0 (Array.length r));;
let rec copy n times sep : string = match times with
	| 0 -> eval n
	| _ -> (eval n)^sep^(copy n (times-1) sep)
and eval (n:node) : string = match n with
	| N l -> List.fold_left (^) "" (List.map eval l)
	| S s -> s
	| R r -> eval (pick r)
	| P -> "."
	| Many(n,t,s) -> let times = t+(range 0 2) in copy n times s
	| O x -> if Random.int 2 = 1 then eval x else ""
	| Filter(fn,n) -> fn (eval n);;

let (^^) text chr = text ^ (String.make 1 chr)
let scramble text =
	let len = String.length text in
	let rec loop i acc tps =
		if i=len then acc else
		if i+1=len then acc^^text.[i] else
			match text.[i], text.[i+1] with
				| ' ', _ -> loop (i+1) (acc^" ") false
				| _ as c, ' ' -> loop (i+1) (acc^^c) false
				| c1, c2 -> if not tps && Random.int 3 = 0 then
					loop (i+2) ((acc^^c2)^^c1) true
				else
					loop (i+2) ((acc^^c1)^^c2) tps
	in loop 0 "" false
	
let () = Random.self_init(); print_string (scramble (eval top))
