Home For Fiction – Blog

for thinking people

There are no ads, nor any corporate masters
How to show support


November 10, 2019

How to Make a JavaScript “Horoscope” Generator

Programming

horoscope, javascript, language, programming, quackery

0 comments

Relax, I haven’t gone crazy. If you thought someone like me suddenly started believing in horoscopes, you’re wrong. Yes, in this post I’ll show you how to make a JavaScript horoscope generator. But the post is about linguistics, programming, and maybe psychology; not astrology.

If anything, my goal making this JavaScript horoscope generator was to show how ridiculously easy it is to produce accurate-seeming phrases that appear to apply to everyone’s individual situation. Simple answers to complex questions, really.

There’s actually a bit of literary background in this, believe it or not. There is a scene in my book The Other Side of Dreams, where the protagonist makes fun of a Tarot card reader:

Indeed, Ahmed thought, he could tell Anna pretty much everything the woman had said, without using any cards. “You are coming up a difficult fork in the road of your life, considering your options. Part of you would like to be more daring, but you are aware of the importance of being cautious. You are inspired by strong feelings, and you will be rewarded in love thanks to your tenacity. Remember to be true to yourself, although you should also be diplomatic, especially considering matters related to business, money, or agreements.” There, it can’t get any easier than that.

And so, I decided to combine my background in languages and my interest in programming. This JavaScript horoscope generator was the result!

JavaScript horoscope generator
I promise you, this JavaScript horoscope generator will not tell your fortune – because there is no such thing. Parenthetically, the code you see on the image is part of the actual code used in the program.

A Tongue-in-cheek JavaScript Horoscope Generator

Before I talk about the ins and outs of this random horoscope generator, let’s first take a look at the program.

This should be self-explanatory, but here’s how to use it: Press “Go” to generate a new random horoscope. If the “Increased Randomness” switch is set to “off”, the program generates slightly less random (but more coherent) combinations. If you set it to “on”, you will get more random options, which though might be less coherent.

You can also select your astrological sign using the relevant buttons. Not that they do anything… They’re dummy buttons – almost; there’s a little Easter egg there somewhere. 😛

Note: The app is hosted on raw.githack.com. Since it’s a free service, performance or uptime can’t be guaranteed. If the page is unresponsive, try a little later.

Click to run the program

How it Works

When you use the program without increased randomization, it just randomly picks from a set of words I have already provided. That’s how ridiculously easy it is to make a “horoscope” and have someone believe it.

If you set increased randomization to “on”, the program communicates with the Datamuse server to get some adjectives that frequently precede certain words. This greatly increases randomness, though it can produce some odd results – for example, you might see something like “…can leave you vulnerable to mere nervousness”.

Also keep in mind that when this is set to “on”, there might be a slight delay in getting back the result, as the Datamuse server might be busy.

The Code

Here’s the script for this JavaScript horoscope generator, which should get you in the ballpark. If you’d like the rest (i.e. the HTML/CSS part), you can find it on my GitHub.

$(document).ready(function(){
	$("#piscButton").click(function(){
		window.open('https://blog.homeforfiction.com/2019/06/19/blake-pisces-meaning-duality-and-the-human-tragedy/');
	});
	$("#btn").click(function(){
		dmAdd();
	});
	$("#btn2").click(function(){
		makeText();
	});	
	let elem = document.getElementById("btn");
	elem.style.backgroundColor = "crimson";

	function dmAdd() {
		if (elem.innerHTML == "Off") {
			elem.innerHTML = "On";
			elem.style.backgroundColor = "darkgreen";
			makeText();
		}
		else {
			elem.innerHTML = "Off";
			elem.style.backgroundColor = "crimson";
			makeText();
		}
	}

	let d = new Date();
	let m = d.getMonth();
	let allMonths = ["January", "February",
                "March", "April", "May", "June", "July",
                "August", "September", "October", "November",
                "December"];
	let month = allMonths[m];
	
	let x, y;
    function randomIt (z) {
        x = Math.floor(Math.random() * z.length);
        y = Math.floor(x);
        return z[y];
    }
	
    let adj1 = ["an intriguing ", "a special ", "a unique ", "a complicated ", "an unordinary ", "an unusual ", "a crucial ", "a confusing "];
    let nn1 = ["period ", "month ", "time ", "point "];
    let conj1 = ["as a result of ", "because of ", "due to ", "following ", "as a consequence of "];
    let det1 = ["many ", "several ", "a few ", "some ", "a number of "];
    let nn2 = ["events ", "occurrences ", "happenings ", "incidents ", "thoughts ", "happenstances ", "coincidences "];
    let vb1 = ["trouble ", "puzzle ", "confuse ", "upset ", "unsettle ", "bother ", "intimidate "];
    let det2 = ["at first, ", "initially, ", "for a while, ", "for a few days, ", "for some time, ", "for some days, ", "temporarily, ", "momentarily, "];
    let vb2 = ["expect ", "find ", "anticipate ", "be getting ", "await ", "be met by "];
    let adj2 = ["much ", "a welcoming sense of ", "sufficient ", "significant ", "at least some ", "some much needed "];
    let nn3 = ["relief ", "comfort ", "support ", "content ", "happiness "];
    let det3 = ["later on. ", "soon enough. ", "at some point. ", "at a later point. ", "in the second half of the month. ", "before you know it. "];
    let det4 = ["Nonetheless, ", "However, ", "Still, ", "Having said that, ", "But still, ", "Nevertheless, ", "In spite of that, ", "And yet, ", "Although, "];
    let vb3 = ["keep in mind ", "remember ", "acknowledge ", "recognize ", "not forget ", "not ignore "];
    let adj3 = ["rapid ", "unexpected ", "fluid ", "swift ", "turbulent ", "unstable "];
    let nn4 = ["changes ", "shifts ", "developments ", "transitions ", "changes of your situation ", "stirs in your circumstances ", "reversals of events ", "commotions of occurrences ", "turns of events ", "disturbances in your routine "];
    let vb4 = ["cause ", "bring about ", "create ", "produce ", "leave you vulnerable to ", "leave you open to ", "leave you susceptible to ", "bring you ", "cause you ", "induce ", "precipitate ", "engender ", "provoke "];
    let nn5 = ["mood swings. ", "confusion. ", "moodiness. ", "agitation. ", "nervousness. ", "disquiet. ", "alarm. ", "uneasiness. ", "anxiety. ", "worry. ", "stress. "];
    let vb5 = ["brings ", "means ", "allows for ", "facilitates ", "is favorable for ", ("can be a good " + randomIt(nn1) + "for " ), "could be suitable for "];
    let adj4 = ["new ", "fresh ", "innovative ", "intriguing ", "promising ", "inspiring "];
    let nn6 = ["opportunities ", "beginnings ", "endeavors ", "plans ", "options ", "choices ", "alternatives "];
    let det5 = ["related to ", "in regard to ", "concerning ", "having to do with ", "pertaining to ", "regarding "];
    let nn7 = ["business ", "money ", "finances ", "creativity ", "work ", "entrepreneurship ", "the job market ", "your professional life "];
    let nn8 = ["love. ", "romance. ", "friendship. ", " socializing. ", "networking. ", "meeting new people. "];
    let det6 = ["Perhaps ", "Maybe ", "Possibly "];
    let vb6 = ["think about ", "have thoughts about ", "consider ", "ponder on ", "deliberate on ", "try to decide on "];
    let nn9 = ["options. ", "choices. ", "alternatives. ", "course of action. ", "future. ", "next move. "];
    let vb7 = ["become ", "feel ", "be "];
    let det7 = ["too ", "excessively ", "unreasonably ", "overly ", "unduly "];
    let adj5 = ["paralyzed ", "hesitant ", "confused ", "indecisive ", "unsure ", "skeptical ", "reluctant "];
	
	makeText();
	
	function makeText() {
		let dmAdj1 = dmAdj2 = ""; 
		let NN2 = randomIt(nn2);
		let NN5 = randomIt(nn5);
		let JJ5 = randomIt(adj5);
		let NN7 = randomIt(nn7);
		let NN8 = randomIt(nn8);

		if (elem.innerHTML === ("On")) {
			fetchTheWord("https://api.datamuse.com/words?rel_jjb=" + NN2).then(function(obj){
				if (obj !=null && obj.length > 0) {
					dmAdj1 = randomIt(obj).word;
					if (NN5 === ("mood swings. ")){
						NN5 == "confusion. ";
					}		
					NN5 = NN5.replace(/[.,\s]/g, "");		
					fetchTheWord("https://api.datamuse.com/words?rel_jjb=" + NN5).then(function(obj){
						if (obj != null && obj.length > 0) {
							dmAdj2 = randomIt(obj).word;
							NN5 = NN5 + "."
							fetchTheWord("https://api.datamuse.com/words?ml=" + JJ5).then(function(obj){
								if (obj != null && obj.length > 0) {
									JJ5 = randomIt(obj).word + " ";
									if (NN7.startsWith("the" ) || NN7.startsWith("your")) {
										NN7 = "business";
									}
									fetchTheWord("https://api.datamuse.com/words?ml=" + NN7).then(function(obj){
										if (obj != null && obj.length > 0) {
											NN7 = randomIt(obj).word + " ";
											if (NN8.startsWith("meeting") || NN8.startsWith("network")) {
												NN8 = "love. ";
											}
											NN8 = NN8.replace(/[.,\s]/g, "");
											fetchTheWord("https://api.datamuse.com/words?ml=" + NN8).then(function(obj){
												if (obj != null && obj.length > 0) {
													NN8 = randomIt(obj).word + ". ";
													finnishSetUp();
												}
												else {
													NN8 = NN8 + ".";
													finnishSetUp();
												}
											});
										}
										else {
											finnishSetUp();
										}
									});
								}
								else {
									finnishSetUp();
								}
							});
						}
						else {
							finnishSetUp();
							NN5 = NN5 + "."
						}
					});
				}
				else {
					finnishSetUp();
				}
			});
		}
		else {
			finnishSetUp();
		}
		
		function finnishSetUp() {
			let dets = avoidDuplicates();
			let det4a = dets[0];
			let det4b = dets[1];
			let det4c = dets[2];

			let finalText = (month + " can be " + randomIt(adj1) + randomIt(nn1) + "in your life, " + randomIt(conj1) + randomIt(det1) + dmAdj1 + " " + NN2 + "that will " + randomIt(vb1) + "you " + randomIt(det2) + "though you should " + randomIt(vb2) + randomIt(adj2) + randomIt(nn3) + randomIt(det3) + det4a + "you should " + randomIt(vb3) + "that such " + randomIt(adj3) + randomIt(nn4) + "can " + randomIt(vb4) + dmAdj2 + " " + NN5 + "\n\n" + det4b + month + " also " + randomIt(vb5) + randomIt(adj4) + randomIt(nn6) + randomIt(det5) + NN7 + "or " + NN8 + randomIt(det6) + "you will " + randomIt(vb6) + "your " + randomIt(nn9) + det4c + "don\'t " + randomIt(vb7) + randomIt(det7) + JJ5 + "about it!");
			
			$('#horo').text(finalText);
		}
		
		function fetchTheWord(url) {
			return new Promise(function (resolve, reject) {
				resolve($.get(url));
			});
		}
		function avoidDuplicates () {
	    	let a = randomIt(det4);
	    	let b = randomIt(det4);
	    	let c = randomIt(det4);
	    	if ((a == b) || (a == c) || (b == c)) {
		    	return ["Nonetheless, ", "However, ", "Still, "];
			}
			else {
			    return [a, b, c];
			}
		}		
	}
});
Punning Walrus shrugging

Comments are closed for posts older than 90 days