Search

Geek Girl Joy

Artificial Intelligence, Simulations & Software

Month

August 2017

Are You Prepared For Disaster?

Hey everyone hope you’re all having a better week than I am! Really though this week is shaping up to be a real peach 🍑!

Folks my little used PT Cruiser  🚙 finally gave up the ghost 👻 and died yesterday. 😦

Thankfully the client I was on my way to meet with understood the situation and was happy to reschedule, but…

What if I only had yesterday to close the deal? What if they were not amenable to rescheduling the meeting? What if that was my one shot? What if I had blown my chance with them & they were the client to make my career? That opportunity might just as easily been lost!

Are you and your business prepared in case some vital part breaks down? Can you keep your doors open if a hurricane hits your area and the flood waters come?  What if consumers simply don’t want the product that you are offering? Do you have a backup plan if your business partner decides to “throw in the towel“? Are you prepared for the looming bear market? I’ll be surprised if the shoe doesn’t drop on that one anytime soon by the way!

Speaking of, ever hear of “Resource Slack“? If not do yourself a favor and get googling my friend! 😉

I am reminded of a situation from years ago when I was a lowly “Information Technology Systems Administrator” that seems applicable right now. You see every time it rained the internet connection coming to the building’s MPOE would simply drop out and we could be without internet connectivity for days! Sometimes this even affected our telecom lines so we were without phone and fax as well. Our business was literally cut off from the rest of the world!

Of course this didn’t affect our warehouse and production line staff all that much, however basically the entire office staff would be displaced to some extent. Naturally this would eat into profits a bit, but simply because we were a manufacturer and our production line would continue to operate, losses were somewhat mitigated.

Customers don’t really care if your Accounting department can’t send out their bills today and the owners know they will go out eventually. If we were really worried about getting paid we  wouldn’t have been doing business with those customers or vendors anyway! Our customer service staff would have to field tons of complaints after everything came back online however that “mess” affects upper management very little.

So while it was an annoyance, there was not a major incentive to resolve the underlying problem… well that is until it really started affecting the nightly EDI transmissions!

If you miss your EDI transmission you will start to rather quickly accrue what are called “EDI chargebacks”. Chargebacks are penalty fees levied by your vendors when you fail to live up to some part of your agreement,  for example: informing them of sales numbers or inventory quantities etc…

So we were instructed to resolve the issue as simply and quickly as possible.. and oh yeah, you have zero additional funds in the budget to do it. In other words “put a band-aid on it and move on”.

We used a mobile “hotspot puck” as a fail-over which acted as a functional “stop gap solution” in the event that the main EDI lines went out due to inclement weather. It wasn’t pretty, but it did work and chargebacks due to telecom outage were kept to a bare minimum.

I think the owner simply did a cost to benefits analysis of the situation and prioritized the issue low on the list. Frankly, I can’t say that I truly disagree with that assessment either!

It rains so infrequently in So Cal that people literally refer to it as “sunny” California!

We’re also known for having multiyear droughts every few years so it does make sense that fixing an otherwise “minor annoyance” wouldn’t be of high importance.

We (the IT staff), would when the proper occasion arose, remind the owners of the issue, but when you have rising production costs, increased regulatory compliance costs, aging machinery, fierce competition for skilled design & production staff… fixing a “minor annoyance” isn’t going to get budgeted!

Time moves on, a few years go by and the issue remained unresolved and then it rained, everything when down again.

We were called in to meet with the owners regarding the issue. “We thought you guys had resolved this already?!”.

Peacefully, diplomatically, calmly… PROFESSIONALLY, we reminded them of the situation and explained our options. After a nice long discussion of the issue we finally got the “go ahead” to get it fixed.

We then spent months working with our ISP and Teleco to track down just where the problem was occurring. We had technicians from each come onsite dozens of times and run all kinds of quality tests on the local loop.

The thing is, it went like most fickle and intermittent issues tend to go, we simply couldn’t locate the source of the problem!

It was all rather maddening simply because, despite your best efforts the problem remains.

It’s like you can start to feel all the eyes of your coworkers, managers and employers on the back of your neck almost screaming “WHY ISN’T IT FIXED YET?”.

The issue was eventually isolated to a ~300 foot (~91.44 meter) segment of buried twisted pair copper. The service provider ended up having to dig up a segment of asphalt in the street to run a new line, and with that our “hotspot puck” solution faded to only a memory.

Now you may be wondering why we got the “dressing down” that ultimately resulted in the problem getting fixed? Well, it turned out that the owners youngest son started attending college in another state (completely across the country actually) and a reliable internet connection was required in order for them to Skype.

The real take away here is that we only ever fix the issues that affect us in meaningful ways and the fact is that despite my best warnings that you “hedge” yourself, your families and businesses against as many of the foreseeable disasters as possible, the truth is that there will still be things you can’t prepare for because you honestly can’t plan for everything! Or it simply may be that you lack the resources to do anything about it and the “band-aid” (if one exists) will have to suffice.

Further, even after my long and dire warning most of you wont take my advice to heart. For most of you, no action will occur to mitigate loses until those losses feel “real” to you, personally.

So back to my predicament, just what the hell am I going to do about my vehicle situation? I need my vehicle to run errands, take Xavier to Dr. checkups, meet with potential clients… etc…

You better believe this feels VERY “real” to me and I honestly was not prepared for a vehicle breakdown!

I try to plan and prepare for the eventuality that anything and everything can and will go wrong (all good geeky tech professional guru’s should know about the bathtub curve and Murphy’s law) but lately things have been really tough financially!

Frankly, I’m not exactly sure how I am going to resolve this one.

I don’t want to say it’s desperate but… the phrase “totally screwed” comes to mind and… well, I’m at a real loss as to what to do about it right now other then to sit here and tell you about it.

Here’s what I do know though, I can’t simply “put a band-aid on it” and ignore the problem until it “rains” again. Doing that would mean that I’d just end up having even more problems to solve and the next time a problem arises, I will be solving that issue without a vehicle and with limited mobility.

So right now I’d like to take this opportunity to say that if you enjoy reading my articles, like the projects I release or simply feel motivated to help me get through this crisis, please consider supporting me over on Patreon and if you are not too keen on Patreon then please consider supporting me by sending Bitcoins to my tip address. Even just a few Satoshi would really go a long way at this point!

Please Send Here: 1GgUHjVAYqFLBWufFTpkoDEti16DSSNNG7

Thank you for listening to my problems and for all your generous support!

 

Much Love,

~Joy

 

Advertisements

Ancestor Simulations The Sol System

Welcome back everyone and happy Monday!

Today of course we will continue examining the topic of Ancestor Simulations.

We have already established how to define our universe by using the Drake Equation and we discussed creating planetary terrain using the Plasma Fractal and last week we even looked at implementing a method of Generating Galaxies using a Logarithmic Spiral.

Today we are going to slow things down just a little. Before we tackle generating new orbits & solar systems for our ancestors to observe and explore (maybe even live in), we will examine our own solar system for inspiration as well as to get a handle on how solar systems “work”.

Thankfully we couldn’t ask for a better example and its right here in our own “backyard”!

From the Wikipedia article on our solar system:

1 Star Sol
8 Known planets
5 Known & recognized

dwarf planets

Ceres, Pluto, Haumea, Makemake, Eris

Currently recognized by the IAU however there are possibly several hundred as yet unrecognized dwarf planets within our system.

Known natural satellites

472 (175 planetary & 297 minor planets)

Known minor planets 707,664  (as of 2016-03-07)
Known comets 3,406  (as of 2016-03-07)
Identified rounded satellites 19

Clearly our system is a ‘treasure trove‘ of not only valuable resources but also information that we can model and test with!

The Sol system is ~100,000 AU astronomical units wide if you include the oort cloud (the remnants of the protoplanetary disk) which is a vast “cloud bubble” of comets, meteoroids, asteroids & planetesimals at the very outer edge of our solar system.

Considering the sheer numbers of objects in our solar system it is infeasible at best to include all of them in our model, or at least all in a single simulation. Consequently, we will focus our attention today on modeling just the first 4 inner planets.

Mercury is the smallest “full sized” planet and it is the closest to the sun at a distance of only ~0.39 AU. Its orbital period around the sun in only 88 days.


////
// Define Mercury
////
$mercury_au_from_sun=0.39; // AU from Sun
$mercury_size=1; // Size
$mercury_grey = imagecolorallocate($system, 100, 100, 100); // Color
$mercury_vy = 1.8; // Velocity
$mercury_vx = 0;   // Velocity
$mercury_x = $mercury_au_from_sun; // Initial x position
$mercury_y = 0; // Initial y position
$mercury_r = sqrt(pow($mercury_x,2) + pow($mercury_y,2)); // Orbital radius at this position
$mercury_a =  1.8 / pow($mercury_r, 2); // Acceleration / angle
$mercury_ax = -$mercury_a * $mercury_x / $mercury_r; // Divide the force for the angle between x & y
$mercury_ay = -$mercury_a * $mercury_y / $mercury_r; // Divide the force for the angle between x & y
// Normalize positions to be within the image bounds
$mercury_row = MinMax($mercury_y, $low, $high, $size);
$mercury_col = MinMax($mercury_x, $low, $high, $size);
// plot mercury
@imagefilledellipse ( $system, round($mercury_row), round($mercury_col), $mercury_size, $mercury_size, $mercury_grey);
if($display_names == true){
	@imagestring ( $system, 5, $mercury_row-$mercury_size+5, $mercury_col-$mercury_size+5, "Mercury", $mercury_grey);
}

echo 'Mercury initialized.' . $line_ending;

Venus is about as large as Earth and is the second closest planet to the sun at a distance of ~0.723 AU. Its orbital period around the sun in only 224.7 days.


////
// Define Venus
////
$venus_au_from_sun=0.723; // AU from Sun
$venus_size=3; // Size
$venus_brown = imagecolorallocate($system, 150, 100, 0); // Color
$venus_vy = 1; // Velocity
$venus_vx = 0; // Velocity
$venus_x = $venus_au_from_sun; // Initial x position
$venus_y = 0; // Initial y position
$venus_r = sqrt(pow($venus_x,2) + pow($venus_y,2)); // Orbital radius at this position
$venus_a =  $venus_au_from_sun / pow($venus_r, 2); // Acceleration / angle
$venus_ax = -$venus_a * $venus_x / $venus_r; // Divide the force for the angle between x & y
$venus_ay = -$venus_a * $venus_y / $venus_r; // Divide the force for the angle between x & y
// Normalize positions to be within the image bounds
$venus_row = MinMax($venus_y, $low, $high, $size);
$venus_col = MinMax($venus_x, $low, $high, $size);
// plot venus
@imagefilledellipse ( $system, round($venus_row), round($venus_col), $venus_size+5, $venus_size, $venus_brown );
if($display_names == true){
    @imagestring ( $system, 5, $venus_row-$venus_size , $venus_col-$venus_size+5 , "Venus" , $venus_brown );
}

echo 'Venus initialized.' . $line_ending;

Earth is the third planet from the sun, currently the only known cradle of life and the planet you are currently on. The AU unit of measure is derived from the distance of the Earth to the sun where earth orbits at a distance of ~1 AU from the sun. Its orbital period around the sun is 365.26 days.


////
// Define Earth
////
$earth_au_from_sun=1;// AU from Sun
$earth_size=4; // Size
$earth_blue = imagecolorallocate($system, 0, 0, 255); // Color
$earth_vy = 1; // Velocity
$earth_vx = 0; // Velocity
$earth_x = $earth_au_from_sun; // Initial x position
$earth_y = 0; // Initial y position
$earth_r = sqrt(pow($earth_x,2) + pow($earth_y,2)); // Orbital radius at this position
$earth_a =  $earth_au_from_sun / pow($earth_r, 2); // Acceleration / angle
$earth_ax = -$earth_a * $earth_x / $earth_r; // Divide the force for the angle between x & y
$earth_ay = -$earth_a * $earth_y / $earth_r; // Divide the force for the angle between x & y
// Normalize positions to be within the image bounds
$earth_row = MinMax($earth_y, $low, $high, $size);
$earth_col = MinMax($earth_x, $low, $high, $size);
// plot earth
@imagefilledellipse ( $system, round($earth_row), round($earth_col), $earth_size, $earth_size, $earth_blue );
if($display_names == true){
    @imagestring ( $system, 5, $earth_row-$earth_size , $earth_col-$earth_size+5 , "Earth" , $earth_blue );
}

echo 'Earth initialized.' . $line_ending;

Mars is the fourth planet from the Sun, the last orbital body we will be modeling today and the second to smallest planet being only larger than Mercury. Mars is 1.524 AU from the sun & its orbital period around the sun is 687 days.


////
// Define Mars
////
$mars_au_from_sun = 1.524; // AU from Sun
$mars_size = 2; // Size
$mars_red = imagecolorallocate($system, 255, 0, 0); // Color
$mars_vy = 0.8; // Velocity
$mars_vx = 0; // Velocity
$mars_x = $mars_au_from_sun; // Initial x position
$mars_y = 0; // Initial y position
$mars_r = sqrt(pow($mars_x,2) + pow($mars_y,2)); // Orbital radius at this position
$mars_a =  $mars_au_from_sun / pow($mars_r, 2); // Acceleration / angle
$mars_ax = -$mars_a * $mars_x / $mars_r; // Divide the force for the angle between x & y
$mars_ay = -$mars_a * $mars_y / $mars_r; // Divide the force for the angle between x & y
// Normalize positions to be within the image bounds
$mars_row = MinMax($mars_y, $low, $high, $size);
$mars_col = MinMax($mars_x, $low, $high, $size);
// plot mars
@imagefilledellipse ( $system, round($mars_row), round($mars_col), $mars_size, $mars_size, $mars_red);
if($display_names == true){
    @imagestring ( $system, 5, $mars_row-$mars_size , $mars_col-$mars_size+5 , "Mars" , $mars_red );
}

echo 'Mars initialized.' . $line_ending;

 

Here is the main simulation loop:


for($i = 0; $i < $simulations; $i++){
	
	////
	// Solar System
	////
    $system = imagecreatetruecolor($size, $size);
	
	
	////
	// Sun
	////
	// Plot Sun
	@imagefilledellipse ( $system, $sun_y, $sun_x, $sun_size, $sun_size, $sun_yellow );
	if($display_names == true){
	    @imagestring ( $system, 5, $sun_x-12 , $sun_y-7 , "Sun" , $space_black );
    }

	////
	// Mercury
	////
    $mercury_vx = $mercury_vx + $mercury_ax * $delta_time; // New velocity
	$mercury_vy = $mercury_vy + $mercury_ay * $delta_time; // New velocity
	$mercury_x = $mercury_x + $mercury_vx * $delta_time; // New position
	$mercury_y = $mercury_y + $mercury_vy * $delta_time; // New position
	$mercury_r = sqrt(pow($mercury_x,2) + pow($mercury_y,2)); // Orbital radius at this position
	$mercury_a =  1.8 / pow($mercury_r, 2); // Acceleration / angle
	$mercury_ax = -$mercury_a * $mercury_x / $mercury_r; // Divide the force for the angle between x & y
	$mercury_ay = -$mercury_a * $mercury_y / $mercury_r; // Divide the force for the angle between x & y
	// Normalize positions to be within the image bounds
	$mercury_row = MinMax($mercury_y, $low, $high, $size);
	$mercury_col = MinMax($mercury_x, $low, $high, $size);
	// Plot Mercury
	@imagefilledellipse ( $system, round($mercury_row), round($mercury_col), $mercury_size, $mercury_size, $mercury_grey );
	if($display_names == true){
	    @imagestring ( $system, 5, $mercury_row-$mercury_size+5, $mercury_col-$mercury_size+5, "Mercury", $mercury_grey);
    }
	
	
	
	////
	// Venus
	////
    $venus_vx = $venus_vx + $venus_ax * $delta_time; // New velocity
	$venus_vy = $venus_vy + $venus_ay * $delta_time; // New velocity
	$venus_x = $venus_x + $venus_vx * $delta_time; // New position
	$venus_y = $venus_y + $venus_vy * $delta_time; // New position
	$venus_r = sqrt(pow($venus_x,2) + pow($venus_y,2)); // Orbital radius at this position	
	$venus_a =  $venus_au_from_sun / pow($venus_r, 2); // Acceleration / angle
	$venus_ax = -$venus_a * $venus_x / $venus_r; // Divide the force for the angle between x & y
	$venus_ay = -$venus_a * $venus_y / $venus_r; // Divide the force for the angle between x & y
	// Normalize positions to be within the image bounds
	$venus_row = MinMax($venus_y, $low, $high, $size);
	$venus_col = MinMax($venus_x, $low, $high, $size);
	// Plot Venus
	@imagefilledellipse ( $system, round($venus_row), round($venus_col), $venus_size, $venus_size, $venus_brown );
	if($display_names == true){
	    @imagestring ( $system, 5, $venus_row-$venus_size , $venus_col-$venus_size+5 , "Venus" , $venus_brown );
    }
	
	
	
	////
	// Earth
	////
    $earth_vx = $earth_vx + $earth_ax * $delta_time; // New velocity
	$earth_vy = $earth_vy + $earth_ay * $delta_time; // New velocity
	$earth_x = $earth_x + $earth_vx * $delta_time; // New position
	$earth_y = $earth_y + $earth_vy * $delta_time; // New position
	$earth_r = sqrt(pow($earth_x,2) + pow($earth_y,2)); // Orbital radius at this position
	$earth_a =  $earth_au_from_sun / pow($earth_r, 2); // Acceleration / angle
	$earth_ax = -$earth_a * $earth_x / $earth_r; // Divide the force for the angle between x & y
	$earth_ay = -$earth_a * $earth_y / $earth_r; // Divide the force for the angle between x & y
	// Normalize positions to be within the image bounds
	$earth_row = MinMax($earth_y, $low, $high, $size);
	$earth_col = MinMax($earth_x, $low, $high, $size);
	// Plot Earth
	@imagefilledellipse ( $system, round($earth_row), round($earth_col), $earth_size, $earth_size, $earth_blue );
	if($display_names == true){
		@imagestring ( $system, 5, $earth_row-$earth_size , $earth_col-$earth_size+5 , "Earth" , $earth_blue );
    }
	
	////
	// Mars
	////
    $mars_vx = $mars_vx + $mars_ax * $delta_time; // New velocity
	$mars_vy = $mars_vy + $mars_ay * $delta_time; // New velocity
	$mars_x = $mars_x + $mars_vx * $delta_time; // New position
	$mars_y = $mars_y + $mars_vy * $delta_time; // New position
	$mars_r = sqrt(pow($mars_x,2) + pow($mars_y,2)); // Orbital radius at this position
	$mars_a =  $mars_au_from_sun / pow($mars_r, 2); // Acceleration / angle
	$mars_ax = -$mars_a * $mars_x / $mars_r; // Divide the force for the angle between x & y
	$mars_ay = -$mars_a * $mars_y / $mars_r; // Divide the force for the angle between x & y
	// Normalize positions to be within the image bounds
	$mars_row = MinMax($mars_y, $low, $high, $size);
	$mars_col = MinMax($mars_x, $low, $high, $size);
	// Plot Mars
	@imagefilledellipse ( $system, round($mars_row), round($mars_col), $mars_size, $mars_size, $mars_red );
	if($display_names == true){
		@imagestring ( $system, 5, $mars_row-$mars_size , $mars_col-$mars_size+5 , "Mars" , $mars_red );
	}

	// Output Solar System
	imagepng($system, "images/" . ($i + 1) . ".png");

	// Free Memory
	imagedestroy($system);
}

You may view a live version of this project here  and you can access the complete source for this project on GitHub here.

You can see the results of this code in the images below.

Inner Sol System – ~1 Earth Year

Inner Sol System - ~1 Earth Year
Click for Full Size Animation

While I have your attention, I’d like to say thanks for reading my articles! It takes a lot of time, planning and ‘TLC‘ to bring you these posts every week and if you like what I’m doing and please support me on Patreon for as little a $1 a month.

 

With that, have a great week & I will see you all in the next post!

Please Like, Comment below & Share this post with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

Much Love,

~Joy

Ancestor Simulations Generating Galaxies Friday Fun Fix

Happy Friday everyone!  Checking in with another Friday Fun Fix.

The hardest challenge I have faced this week has been lack of sleep… well, most weeks actually. 😛

Xavier has been in this pattern where he has been ‘cat napping‘ his way through the night and day rather than nice consistent longer sleep cycles. Consequently I have found it difficult to obtain sufficient sleep myself. I literally passed out for an hour on Wednesday and didn’t even realize I had slept! Xavier was playing in his crib and didn’t even notice.

When I woke up… I noticed the time and realized I had “lost” an hour of productivity to sleep. Most days I’m tired but Tuesday Night / Wednesday morning left me completely exhausted!

Thankfully Xavier let me get some rest Wednesday evening and while even now I’m still tired, looking at the glowing LCD screen in front of me… let alone reading math notation and programming doesn’t just flat out hurt. All those years of late night “crunch programming” sessions to finish a feature are finally paying off as preparation for motherhood! 😛

In anycase, I didn’t have a ton of time to work on adding anything to the Galaxy generator however I did refactor the code a little to simplify redundancy.

Further, adding additional features to the Galaxy generator doesn’t seem all that necessary at this time and I am happy with where it is currently and feel comfortable moving forward on Monday. That isn’t to say that I don’t have plenty of ideas on how to improve and extend it, just that we will implement them when they are necessary.

My code refactoring eliminated 16 lines of redundant code taking the Galaxy generator from 304 lines of code down to 288.

You may view a live version of this project here if you would like and access the source for this project on GitHub here.

Here  is one more sample image for your enjoyment. This MASSIVE image is 8192x8192px and contains ~ 1/44,444th the number of stars in our actual galaxy (the Milky Way). Click the image below to open it and then zoom in… really makes you ponder how vast our universe really is when you consider that despite using a huge image and filling it with as many stars as I reasonably could, it still pales in comparison to the real thing!

Please Like, Comment below & Share this post with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Ancestor Simulations Generating Galaxies

Welcome back to another installment of my Ancestor Simulations series, previous posts in this series series are:

Carl Sagan famously wrote these two excerpts in his book Cosmos:

“If you wish to make an apple pie from scratch, you must first invent the universe.” & “The nitrogen in our DNA, the calcium in our teeth, the iron in our blood, the carbon in our apple pies were made in the interiors of collapsing stars. We are made of star stuff.”

Fundamentally what Mr. Sagan is talking about is that we are “here and now” in ‘spacetime‘ and that everything you see around you, from the seemingly mundane soil beneath your feet to the silicon chips in the device you’re using to read this post right down to even the very constituents of your own body all originate not here on earth, but out there among the stars!

Our Sun (Sol) is ~4.6 billion years old and when our solar system formed, it did so by accreting and coalescing material already present in our galaxy. It turns out that microgravity is an incredibly potent force for for creating emergent larger structures (like galaxies and solar systems) from small clumps of available materials. Those materials came from somewhere outside our solar system (we are the remnants of other long dead solar systems) to form or become our solar system (the Sol system).

Below I have linked to a a video of Astronaut Don Pettit PhD and Science Officer for Expedition 6 of the ISS explaining an experiment he conducted that illustrates how microgravity would have operated in our early solar system to take “small particles that are bouncing around colliding with each other and coagulating into larger agglomerates”.

Those “small particles” Mr. Pettit is talking about in his experiment were salt (NaCl) and is analogous to the ‘Interstellar Medium‘  which is ultimately the byproduct of the life cycles of stars that existed and “died” before our system had even formed.

In time (~5 Billion years from now) our sun is expected to expand into a ‘Red Giant‘ at which point it is believed that it will consume our little Earth and anything still around on the planet. If Sol remains intact and isn’t itself consumed by a black hole or by some other celestial body, it will progress through it’s life cycle to become a ‘White Dwarf‘. Trillions of years later Sol may eventually become a ‘Black Dwarf‘ star after scattering it’s heavy elements into interstellar space as a ‘Planetary Nebula‘ thereby sowing the seeds (that ‘star stuff’ Mr. Sagan wrote about) of countless other worlds, some of which may eventually harbor life just like our solar system does now. Some of that ‘star stuff’, will be the very same particles that are part of your body at this very moment!

The Milky Way‘ (our home galaxy) is a vast area spanning ~100,000 light years in diameter and and ~2000 light years thick. It is estimated that the Milky Way Galaxy is ~13.7 Billion years old, making it almost as old as the universe itself!

Which now brings us to this week’s project, Generating Galaxies. The method we will use to create galaxies today is called a Logarithmic Spiral and it will allow us to create all the main distinct types of galaxy: Spiral, Quasar, Globular & Irregular.

So without further hemming and hawing, here is our code:



set_time_limit(300); // 5 Minutes adjust as needed
ini_set('memory_limit', '3G'); // 3 GB Adjust as needed

function RandomFloat(){
    return '0.'. mt_rand(0,9999);
}

function MinMax($value, $min, $max, $size){
    return abs(($value - $min) / ($max - $min) * $size);
}

function vignette($im){
    $width = imagesx($im);
    $height = imagesy($im);

    for($row = 0; $row < $width; ++$row){
        for($col = 0; $col < imagesy($im); ++$col){  
            $index = imagecolorat($im, $row, $col);
            $rgb = imagecolorsforindex($im, $index);
            $sharp = 1; // 0 - 10 small is sharpnes, 
            $level = 0.7; // 0 - 1 small is brighter    
            $l = sin((pi() + RandomFloat()) / $width * $row) * sin((pi() +  RandomFloat()) / $height * $col);
            $l = pow($l, $sharp); 
            $l = 1 - $level * (1.2 - $l);
            $rgb['red'] *= $l;
            $rgb['green'] *= $l;
            $rgb['blue'] *= $l;
            $color = imagecolorallocate($im, $rgb['red'], $rgb['green'], $rgb['blue']);
            imagesetpixel($im, $row, $col, $color);  
        }
    }
    return(true);
}

if(isset($_POST["galaxy-type"])){$galaxy_type = $_POST["galaxy-type"];}
else{$galaxy_type = 'spiral';}


if(isset($_POST["exponent"])){$exponent = $_POST["exponent"];}
else{$exponent = 9;}

$size = pow(2, $exponent);

if(isset($_POST["apply-gaussian"])){$apply_gaussian = $_POST["apply-gaussian"];}
else{$apply_gaussian = false;}

if(isset($_POST["apply-colorize"])){$apply_colorize = $_POST["apply-colorize"];}
else{$apply_colorize = false;}

if(isset($_POST["red"])){$red_number = $_POST["red"];}
else{$red_number = mt_rand(0,255);}

if(isset($_POST["green"])){$green_number = $_POST["green"];}
else{$green_number = mt_rand(0,255);}

if(isset($_POST["blue"])){$blue_number = $_POST["blue"];}
else{$blue_number = mt_rand(0,255);}

if(isset($_POST["apply-greyscale"])){$apply_greyscale = $_POST["apply-greyscale"];}
else{$apply_greyscale = false;}

if(isset($_POST["apply-negate"])){$apply_negate = $_POST["apply-negate"];}
else{$apply_negate = false;}

if(isset($_POST["apply-vignette"])){$apply_vignette = $_POST["apply-vignette"];}
else{$apply_vignette = false;}


if(isset($_POST["number-of-stars"])){$number_of_stars = $_POST["number-of-stars"];}
else{$number_of_stars = 300000;}

$a = 0.9759 + RandomFloat();
$b = 0.1759; // ~nautilus shell
$steps = 5; 
$radius = 3 * pi()* $steps;
$max_spread = 0.3;
$min_star_position = -76458.735624534;
$max_star_position = 102693.535433 ;

// Image Resource
$galaxy = imagecreatetruecolor($size, $size);

// Colors
$white = imagecolorallocate($galaxy, 255, 255, 255);
$yellow = imagecolorallocate($galaxy, 255,255,0);
$red = imagecolorallocate($galaxy, 255,0,0);
$blue = imagecolorallocate($galaxy, 0,0,255);
$black = imagecolorallocate($galaxy, 0, 0, 0);
$dark_grey = imagecolorallocate($galaxy, 50, 50, 50);

// Create Image of Galaxy
for($i = 0; $i  $number_of_stars * 0.6){
          $radius = 6 * pi()* $steps; // increase radius and spread out
      }
   }
   elseif($galaxy_type == 'quasar'){// Quasar Galaxy
      if($a != 1){
          $a = mt_rand(1, 2) + RandomFloat();
          $b = 0.2;
          $max_spread = RandomFloat();
      }
      
      $row = $a * exp($b * $angle) * cosh($angle);
      $row = $row + ($max_spread * $row * RandomFloat()) - ($max_spread * $row * RandomFloat());
      $col = $a * exp($b * $angle) * sinh($angle); 
      $col = $col + ($max_spread * $col * RandomFloat()) - ($max_spread * $col * RandomFloat());
  }
  elseif($galaxy_type == 'globular'){// Globular/Elliptical Galaxy
      if($max_spread != 1){     
          $a = mt_rand(1, 2) + RandomFloat();
          $b = 0.2;      
          $max_spread = 1;
          $radius = 6 * pi()* $steps;
      }
      
      $row = $a * exp($b * $angle) * cos($angle);
      $row = $row + ($max_spread * $row * RandomFloat()) - ($max_spread * $row * RandomFloat());
      $col = $a * exp($b * $angle) * sin($angle); 
      $col = $col + ($max_spread * $col * RandomFloat()) - ($max_spread * $col * RandomFloat());
  }
  elseif($galaxy_type == 'irregular'){// Irregular Galaxy
      if($max_spread != 1){     
          $a = 8 + RandomFloat();
          $b = 0.2;      
          $max_spread = 1.3;
          $radius = 6 * pi()* $steps;
      }
      
      $row = $a * exp($b * $angle) * cos($angle);
      $row = $row + ($max_spread * $row * RandomFloat()) - ($max_spread * $row * RandomFloat());
      $col = $a * exp($b * $angle) * sin($angle); 
      $col = $col + ($max_spread * $col * RandomFloat()) - ($max_spread * $col * RandomFloat());
  }
    
  // Flip a coin to determine which arm 
  // the star should be on.
  if (mt_rand(0, 1) == 1){
      // if heads put it on the second arm
      // by inverting the values
      $row = ($row/-1);
      $col = ($col/-1);
  } 

  // Normalize positions to be within the image bounds
  $row = MinMax($row, $min_star_position, $max_star_position, $size);
  $col = MinMax($col, $min_star_position, $max_star_position, $size);

  
  $colors = array($white, $white, $white, $dark_grey, $yellow, $red, $blue);
  @imagesetpixel($galaxy,round($row),round($col), $colors[mt_rand(0,6)]); // Plot the star position
}

if($apply_gaussian == true){
    imagefilter($galaxy, IMG_FILTER_GAUSSIAN_BLUR); // blur
}
if($apply_colorize == true){
    @imagefilter($galaxy, IMG_FILTER_COLORIZE, $red_number, $green_number, $blue_number); // Shift colors
}
if($apply_greyscale == true){
    @imagefilter($galaxy,  IMG_FILTER_GRAYSCALE); // grey scale
}
if($apply_negate == true){
    @imagefilter($galaxy, IMG_FILTER_NEGATE); // inverse colors
}
if($apply_vignette == true){
    @vignette($galaxy); // vignette
}


// Output image
imagepng($galaxy, "galaxy.png");

// free memory
imagedestroy($galaxy);

You may view a live version of this project here if you would like and access the source for this project on GitHub here.

You can see the results of this code in the images below.

Click for Full Size Images

Spiral

Globular

Quasar

Irregular

That’s it for today ladies and gentlemen.

Please Like, Comment below & Share this post with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Ancestor Simulations Generating Planet Terrain Friday Fun Fix

Surprise Friday post everybody! 😋

First, relax. Yes you will get another post on Monday, I’m working on the next part of our Ancestor Simulation and I think I have something you will really enjoy but in the mean time I wanted to do a second post on Generating Planet Terrain.

Why a second post? Well, to be honest… I know the week long wait for more projects is tough, so I’m trying to produce more content for you guys! I tend to prefer to focus on creating quality projects and code and frankly that takes time, but I know some of you really need your fix. So, I’m experimenting with the idea of “documenting the process” as a way of letting you guys “peer behind the curtain” so to speak.

I can’t guarantee I will  always do a second post or that I will only do two posts. I’m merely committing to produce more content on the whole and this post is part of that.

Anyway, I hope you have been enjoying the Ancestor Simulation series, I have received an overwhelming positive response from my readers about this topic and that might strike you as quite odd when you consider the fact that my content is quite “dry” and frequently full of long complex code but I think that speaks to the idea that if you make your content interesting enough your ‘target audience’  (the smart techies who read my posts) will keep coming back, and for that… I am very grateful! 🙂

So on to Ancestor Simulations. No code today, or rather if you want to get the updated code you can get a copy of this project over on GitHub for free. While you are there be sure to follow me and star the repo so I know you like where the project is going. Speaking of which… just how far am I willing to go with this project? Well that depends on you guys, keep letting me know you are interested and feel free to suggest anything you want to see our sim do and I will see if I can’t accommodate 😉 however ultimately I am implementing this for myself because I find it interesting, I hope you do as well.

This past Monday I posted the Generating Planet Terrain post and before we move forward I wanted to add a few additional features and changes:

  1. More color variation possibilities via an additional ‘Color Variance’ pass over the terrain data and more manual access to the coloring system. It’s still based on a ‘Terrain Color Palette’ however this second pass allows MANY more color combinations which ultimately makes each planet feel more unique and special.
  2. Added a Generate Random button.
  3. Slight change to the water system.
  4. Slight change to the ice system.
  5. Added a ‘Display Type’ setting so you can now view the map as a ‘Map’ (as before) or as a ‘Planet’ (see below).

You can of course preview a running version here.

And with that I hope you all have a great weekend and I will see you Monday.

Click for Full Size Images

Please Like,  Share my posts with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Ancestor Simulations Generating Planet Terrain

Welcome back, I hope you have been missing me all week! 😛

It’s Monday which means that it’s time to continue with the second installment of our Ancestor Simulations series.

Last week I introduced the topic of Ancestor Simulations and illustrated how we can implement a version of Drake’s Equation ( N = R* * fp * Ne * fl * fi * fc * L ) so that we can probabilistically run many different simulations on a hypothetical galaxy (or even universe) and depending on the values we input for the axioms of equation we get vastly different types of galactic neighborhoods. In some simulations the universe is a vast empty space that is cold & lifeless, yet in others it is teeming with life practically a stones throw outside of our local star group in any direction you care to look. I won’t venture to speculate if they really are out there or not but I will give you a quote by Carl Sagan that I like:

“The universe is a pretty big place. If it’s just us, seems like an awful waste of space.”

Now that we have an equation for defining and describing the universe that our simulation takes place in we will want to find number ranges we feel comfortable with for our simulation and cache them at some point so we can make use of them in other parts of the simulation but for now I would like to move away from Drake’s Equation and move to a more practical challenge.

In order for our “ancestors” to be comfortable and build happy productive lives for themselves they will need a place to live. We have Earth to call our home sweet chunk of terraferma 😛

However I think a kind of a fun aspect to this project is that the so called “ancestors” need not be our ancestors and, hell they need not even be primates! They could end up being intelligent arthropods if we were to build some kind of genetic evolutionary system!

So because it’s far more interesting (not to mention more useful) to generate a terrain from scratch than to simply use a pre-rendered picture or mesh of earth (especially if we are not simulating earth)  it becomes evident that we need an algorithm to build a planetary terrain before we can even consider concepts like evolution creating critters.

The algorithm I selected is sometimes called the ‘Plasma fractal’ (which goes hand in hand with the post I did not that long ago about Sierpinski Triangle’s called A Chaos Game ) though most people probably better know this algorithm as the ‘Diamond Square Algorithm‘.

The Plasma Fractal Algorithm

The plasma ‘diamond-square’ algorithm begins with a 2D square array of width and height 2n +1.

That looks like this in code

$size = pow(2, $exponent);

Basically this says take the number 2 and multiply it by n (the Exponent). In my implementation I start the grid count in the top left corner as row: 0  col: 0 (as opposed to (1,1)) therefore I do not have to add 1 to the $size variable.

We then create our 2D array:

$terrain = array_fill(0, $size+1, array_fill(0, $size+1, NULL));

Basically this says create and array of arrays $size+1 wide and $size+1 high and fill the spaces with NULL characters.

Now we start creating the terrain

The four corner points of the array are assigned initial random values within a range (lets say -4 through 4).


$a = $terrain[0][0] = mt_rand($min_roughness, $max_roughness);
$b = $terrain[0][$size] = mt_rand($min_roughness, $max_roughness);
$c = $terrain[$size][0] = mt_rand($min_roughness, $max_roughness);
$d = $terrain[$size][$size] = mt_rand($min_roughness, $max_roughness);

 

Find the center and compute the average

Next you compute the average of the 4 outer squares, find the center square and set it’s value to be the average of the 4 outer square positions + random value within a range.


$average = $a + $b + $c + $d;

$row = $size/2;
$col = $size/2;
$e = $terrain[$row][$col] = ( $average + mt_rand($min_roughness, $max_roughness)) / 5;

 

Divide, Rinse, Repeat

Now all that is left to do is to iterate through the array and perform the  square & diamond steps until all positions in the array have been set. Each time you iterate through the array you divide the array into smaller and smaller “chunks” of equal size and step through each chunk of the array doing the diamond and square walks.

That looks like this:


$chunk_size = $size;
for($level = 1; ($chunk_size / $level) > 0.1; $level++){
	for($row_offset = 0; $row_offset <= $size; $row_offset+=$chunk_size){
		for($col_offset = 0; $col_offset <= $size; $col_offset+=$chunk_size){
			
			// Do (Diamond Step)
			// if the position is not already set then set it
			if(!isset($terrain[$row_offset - $chunk_size/2][$col_offset])){
				$terrain[$row_offset - $chunk_size/2][$col_offset] = ($average + mt_rand($min_roughness, $max_roughness)) / 5;
			}
			$a = $terrain[$row_offset - $chunk_size/2][$col_offset];
			
                        // if the position is not already set then set it
			if(!isset($terrain[$row_offset][$col_offset - $chunk_size/2])){
				$terrain[$row_offset][$col_offset - $chunk_size/2] = ($average + mt_rand($min_roughness, $max_roughness)) / 5;
			}
			$b = $terrain[$row_offset][$col_offset - $chunk_size/2];
			
			// if the position is not already set then set it
			if(!isset($terrain[$row_offset][$col_offset + $chunk_size/2])){
				$terrain[$row_offset][$col_offset + $chunk_size/2] = ($average + mt_rand($min_roughness, $max_roughness)) / 5;
			}
			$c = $terrain[$row_offset][$col_offset + $chunk_size/2];
			
			// if the position is not already set then set it
			if(!isset($terrain[$row_offset + $chunk_size/2][$col_offset])){
				$terrain[$row_offset + $chunk_size/2][$col_offset] = ($average + mt_rand($min_roughness, $max_roughness)) / 5;
			}
			$d = $terrain[$row_offset + $chunk_size/2][$col_offset];
			
			// Compute the average height of $a + $b + $c + $d
			$average = $a + $b + $c + $d;
						
			// Set Center (Square Step)
			// if the position is not already set then set it
			if(!isset($terrain[$row_offset + $chunk_size/2][$col_offset + $chunk_size/2])){
				$terrain[$row_offset + $chunk_size/2][$col_offset + $chunk_size/2] = ($average + mt_rand($min_roughness, $max_roughness)) / 5;
			}
			$e = $terrain[$row_offset + $chunk_size/2][$col_offset + $chunk_size/2];
		}
	}

	// Reduce the chunk size
	$chunk_size = $chunk_size/2;
}

 

After which you simply create an image that is the same size of the array and use the array values as the colors. Lower values should be darker and higher values should be lighter. Water is added by declaring a constant water level and anything below a given level is water and colored the same but as shades of blue.

Putting it all together

And with that all you have to do is create an HTML interface!

Preview a running version of this project here and get your copy of the entire project over on GitHub here.

Click for Full Size Images

Small Lush Islands

 

Desert

 

Lush Landmass with Large Lakes

 

Lunar Like Surface

Obviously more can be added to the generator however this is a great jumping off point to get you started! If you have any thoughts or ideas on improvements or you simply like these kinds of posts go ahead and leave a comment below.

Please Like,  Share my posts with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Ancestor Simulations and Drakes Equation

Today we are going to begin exploring the concept of Ancestor Simulations. Why “ancestor simulations”?  Well as you know, I am GeekGirlJoy (I should really trademark that huh? 😛 Let’s just say I call dibs! 😉 ) so I enjoy SCIENCE!!! therefore what better way to get paid than to employ my 1337 compsci skills by teaching you a little something about simulations and amuse myself with my own virtual denizens in the process… come closer padawan there is much to discuss…

In a nutshell the concept proposed by Nick Bostrom in 2003 goes like this:

  1. “The fraction of human-level civilizations that reach a posthuman stage (that is, one capable of running high-fidelity ancestor simulations) is very close to zero”, or
  2. “The fraction of posthuman civilizations that are interested in running ancestor-simulations is very close to zero”, or
  3. “The fraction of all people with our kind of experiences that are living in a simulation is very close to one”

Personally I tend to agree with #1 outright simply because it “jibe’s right” although it is important to stress that “very close to zero” part. Very close to zero is NOT zero and even if the odds of there being other intelligent “tool making” species who have advanced to the point of being so called “posthuman” are really low, it’s not zero.

Further, if you spend any time at all considering the Drake Equation you are forced to consider the possibility if not outright conclude that even if they are so far away that we can never see or communicate with them they must be there and, likely not just a handful either!

Below is some code so you can experiment with the Drake Equation yourself! Its setup so that you can call the DrakeEquation() function without arguments and it will randomly select values within the appropriate margins.

The Drake Equation: N = (R* * fp * Ne * fl * fi * fc * L)

 


<?php

// Reference the Drake Equation: https://en.wikipedia.org/wiki/Drake_equation

function DrakeEquation($Rs = 0, $Fp = 0, $Ne = 0, $Fl = 0, $Fi = 0, $Fc = 0, $L = 0){

	// The average rate of star formation in our galaxy.
	// Per the aforementioned Wiki Article:
	/*
	Latest calculations from NASA and the European Space Agency indicate that the current rate of star formation in our galaxy is about 0.68–1.45 M☉ of material per year.[26][27] To get the number of stars per year, this must account for the initial mass function (IMF) for stars, where the average new star mass is about 0.5 M☉.[28] This gives a star formation rate of about 1.5–3 stars per year.
	*/
	if(empty($Rs)){
	    $Rs = mt_rand(0,3) . '.' . mt_rand(0,99);
	}

	// Fraction of stars with so called "Habitable planets".
	// Per the aforementioned Wiki Article:
	/*
	Recent analysis of microlensing surveys has found that fp may approach 1—that is, stars are orbited by planets as a rule, rather than the exception; and that there are one or more bound planets per Milky Way star.[29][30]
	*/
	if(empty($Fp)){
		$Fp_decimal = mt_rand(0,99); 
		if($Fp_decimal == 0)
		{
			$Fp_decimal = mt_rand(0,9); // this may not be absolute 0
			                            // so if it is we will set it to 1/100th - 9/100th
		}
	    $Fp = "0.$Fp_decimal";
    }
	
	
	

	// Average number of planets that can potentially support life per star that has planets
	// Per the aforementioned Wiki Article:
	/*
	In November 2013, astronomers reported, based on Kepler space mission data, that there could be as many as 40 billion Earth-sized planets orbiting in the habitable zones of sun-like stars and red dwarf stars within the Milky Way Galaxy.[31][32] 11 billion of these estimated planets may be orbiting sun-like stars.[33] Since there are about 100 billion stars in the galaxy, this implies fp · ne is roughly 0.4. The nearest planet in the habitable zone may be as little as 12 light-years away, according to the scientists.[31][32]
	*/
	if(empty($Ne)){
		$Ne_decimal = mt_rand(0,99); 
		if($Ne_decimal == 0)
		{
			$Ne_decimal = mt_rand(0,9); // this may not be absolute 0 since were here
			                            // so if it is we will set it to 1/100th - 9/100th
		}
	    $Ne = mt_rand(0,1) . '.' . $Ne_decimal;
    }

	// Fraction of habitable planets that actually develop life.
	/* 
	We're here (humans) so it can't be 0.00 and we don't know that it's 1.00 because then it would mean that wherever life evolves, intelligent live WILL ALWAYS evolve EVENTUALLY... and we don't know that is the case, so we'll set this as such:
	*/
	if(empty($Fl)){
		$Fl_decimal = mt_rand(0,99); 
		if($Fl_decimal == 0)
		{
			$Fl_decimal = mt_rand(0,9); // this may not be absolute 0
			                            // so if it is we will set it to 1/100th - 9/100th
		}
		$Fl = "0.$Fl_decimal";
    }

	// Fraction of habitable planets with life on them that also evolve intelligent life
	/*
	Defined using the "short scale" https://en.wikipedia.org/wiki/Long_and_short_scales
	0.001 one of one thousand planets with life, will evolve intelligent life.
	0.0001 one out of ten thousand planets with life, will evolve intelligent life.
	0.00001 one out of one hundred thousand planets with life, will evolve intelligent life.
	0.000001 one out of one million planets with life, will evolve intelligent life.
	0.0000001 one out of ten million planets with life, will evolve intelligent life.
	0.00000001 one out of one hundred million planets with life, will evolve intelligent life.
	0.000000001 one out of one billion planets with life, will evolve intelligent life.
	0.0000000001 one out of ten billion planets with life, will evolve intelligent life.
	0.00000000001 one out of one hundred billion planets with life, will evolve intelligent life.
	0.000000000001 one  out of one trillion planets with life, will evolve intelligent life.
	*/
	$Fi = '0.00' . str_repeat('0', mt_rand(0,9)) . '1';

	// Fraction that survive long enough to sufficiently develop long range communications technology (wireless transmissions)
	if(empty($Fc)){
		$Fc_decimal = mt_rand(0,99); 
		if($Fc_decimal == 0)
		{
			$Fc_decimal = mt_rand(0,9); // this may not be absolute 0
			                            // so if it is we will set it to 1/100th - 9/100th
		}
		$Fc = "0.$Fc_decimal";
    }

	
	// How long those civilizations last
	$L = mt_rand(500,25000); // Anyone's guess could be indefinite
	                         // So lets have it max at 25K years

	return $Rs * $Fp * $Ne * $Fl * $Fi * $Fc * $L;

}

// the number of planets with detectable signs of life
echo DrakeEquation();

?>

 

If you would like to get a copy of this code you can get it over on GitHub here.

It’s important to note two things however:

  1. The value returned by the Drake Equation represent how many other advanced civilizations (aliens) there are and the values returned by the Drake Equation will fluctuate depending on the values used.
  2. Because not all the values are known and we have to guess at what they are, we tend to think of the Drake Equation not as an algorithm that yields truth (like e=MC2) but rather as a tool that helps us test the possibilities.

In regards to Bostrum’s #2, no arguments here. It is basically just saying that even if possible to do so, many civilizations will simply opt not to do so, whatever their reasons may be, but again even if just a few or even one (us/humans) chose to do so then #2 becomes “irrelevant” because not ALL civilizations will chose to do ancestor simulations but some (we/humans) will.

This brings us to #3, basically Bostrom is saying that if #1 & #2 are not absolutely false (ZERO), #3 has to be correct simply due to probability. I definitely concede points 1 & 2. However #3 is saying that YOU & I must conclude that the odds are VERY high that you and I are in one of those so called “ancestor simulations”, so therefore we must be.

This one bothers me a bit… not because I have any real problem with the idea we are all living in a simulation, we could be, however it simply seems like a “lazy” conclusion that isn’t substantiated by any empirical evidence.

Yes, its true I asked you to consider the Drake Equation but I would be remiss in leading you to believe that you should accept any of the numbers produced by it as hard facts and not thought experiments. Although one day we may know all the right values to use in the Drake Equation and then of course it would rest on a solid empirical footing.

Having a high probability that we are in a simulated reality does not automatically make it so and I will give you some examples.

Consider the US “Powerball” Lottery.  the odds are 175,223,510 to 1 against you, for a probability of 0.0000005707% of wining. Put a different way, 1 out of 175 Million tickets should win the “Grand Prize”… but even with such long odds… people play and still win. Most lose, the game requires it in fact and you would basically be correct in believing that if you bought a handful of tickets every day of your life you would still lose. However, people say hang the odds and promptly lose their money but 0.0000005707% of them… win.

Now consider image recognition Neural Networks, they basically operate off of probability and even though they can get amazingly accurate with their responses, they DO make errors (see wiki articles on Confabulation for example) because of their probabilistic approach to problem solving. There are examples where white noise images are given to Convolution Neural Networks and they will say it’s a dog or something even though it’s clearly evident to you and I that it is not a dog.

I could also point out that your odds of dying in a commercial plane are something like one one-hundred-thousandth of one percent (.000014% – basically impossible) and yet here is a list of all the commercial airplane crashes that based on probability should not have happened!

My point is to show that operating on probability alone is not enough! It’s not enough to say that we are “probably” in a simulation therefore we are because even if the odds are exceedingly against us being in “base reality” (true non-simulated reality) it fails to prove or disprove anything and as proofs of my position I have provided the examples that some people win the lotto, neural networks occasionally make mistakes and airplanes do occasionally fall out of the sky!

Now that we are past the hurdle of if we are or not in a simulation, the answer is it doesn’t matter and to quote Rick Sanchez (Rick and Morty) “it’s best not to think about it” :-P, we can talk about building an Ancestor Simulation of our very own!

It goes without saying that our simulated creatures will not be “conscious” or “self-aware” like you and I and therefore falls short of a true Ancestor Simulation like Bostrum is talking about but it very well could be our code base that leads to the creation of the first real ancestor sim.

In any event I will be developing this concept over the next week and I hope have something really interesting to bring you next Monday!

Please Like, Comment & Share my posts with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Tickle the Monday Ivories

Its Monday so hopefully I can bring even just a little Joy into your life today! 😛

Mondays are sort of my Friday in the sense that I’ve tied up all lose ends from the previous week, updated my clients on their projects or sites, fed Xavier countless times (and changed almost as many diapers) and generally my 80ish hour work week is coming to a close, though I don’t have long to ‘rest on my laurels‘, its back to the grind this evening but right now I owe you all a project don’t I? 😉

As you may know I am funding this little experiment with the proceeds I get on Patreon and as such I am limited sometimes in what I can do for you guys in some ways. This does provide me with a nice challenge every week to bring you something interesting that also costs me nothing and generally this has not been an issue since most of the projects we’ve done together have been “back-end” code focusing on PHP and C# with the exception of the Magic 8 Ball post I published in February.

This post will again showcase a “front-end” project that could run right here on this page save for the fact that I am currently using a free WordPress.com account instead of a paid account with more features or more preferentially something like a VPS which will let us do basically whatever we wanted. Now of course there are other options and when it’s time I will weigh the options and ensure that we get the most bang for our buck (meaning the highest marginal utility for the lowest marginal cost) but until then, most unfortunately WordPress.com wont let me embed any functional code on these pages and that includes JavaScript.

Additionally, there are times when you will see ads on my content. I get nothing from them and I cannot remove them. So, if you like these posts and would like MORE out of each then head over to Patreon and drop a buck or more in my hat every month and you will be making a meaningful contribution to growing the quality of my content and at only $12 a year that’s a huge bargain!

So with that, lets to a little Q&A on today’s project.

Q: Why a Piano/Keyboard?

A: Cause its cool! Next question. 😛

Q: Why is there is no PHP in this post?

A: There is actually a tiny amount of PHP in this project which I use to switch between the SVG and the PNG but outside of that there is no PHP tied into the core of this project. I honestly thought about it but  I wanted to keep it simple. Building a music playing neural network on top of the piano did cross my mind but again, this post is about showing that we can build something entirely awesome without it also being overly complex so… I nixed it. Maybe some other time. 😉

Q: Why do the same project using SVG and PNG?

A: The first and most simplest reason is to demonstrate the principal of there being more than one way to do something, but also because there are differences. The SVG uses inline hyper links wrapped around the <g> (groups) in the SVG whereas the PNG uses an image map with the Javascript instead attaching to the link in the map and not the image itself.

Of course the SVG will scale flawlessly on any size screen and the PNG is shorter to code out but will get pixelated the more you zoom in or resize it to be larger.

 

Playable Piano / Keyboard

This could be playable! Support me on Patreon so projects like this can be previewed.

keyboard

Live Preview

You can preview a live version of this project over here

The Code


<!DOCTYPE html>
<html>
    <head>
        <title>Playable SVG & PNG Keyboard</title>
        <style>
        body {
            margin: 0;
            padding: 0;
            text-align: center; /* !!! */
            background-color: #222222;
        }
        h1,p {
            color:white;
        }

        .centered {
            margin: 0 auto;
            text-align: left;
            width: 600px;
        }
        </style>
    </head>
    <body>
        <audio id="C-Audio"><source src="audio/C.wav" type="audio/wav">
          Your browser doesn't support the audio element.
        </audio>
        <audio id="D-Audio"><source src="audio/D.wav" type="audio/wav"></audio>
        <audio id="E-Audio"><source src="audio/E.wav" type="audio/wav"></audio>
        <audio id="F-Audio"><source src="audio/F.wav" type="audio/wav"></audio>
        <audio id="G-Audio"><source src="audio/G.wav" type="audio/wav"></audio>
        <audio id="A-Audio"><source src="audio/A.wav" type="audio/wav"></audio>
        <audio id="B-Audio"><source src="audio/B.wav" type="audio/wav"></audio>
        <audio id="C-Sharp-Audio"><source src="audio/C-Sharp.wav" type="audio/wav"></audio>
        <audio id="D-Sharp-Audio"><source src="audio/D-Sharp.wav" type="audio/wav"></audio>
        <audio id="F-Sharp-Audio"><source src="audio/F-Sharp.wav" type="audio/wav"></audio>
        <audio id="G-Sharp-Audio"><source src="audio/G-Sharp.wav" type="audio/wav"></audio>
        <audio id="A-Sharp-Audio"><source src="audio/A-Sharp.wav" type="audio/wav"></audio>


        <?php
        if(isset($_POST['method'])){
            $method = $_POST['method'];
        }
        else{
        $method = "svg";
        }
        ?>

        <div class="centered">
        <?php if($method == "svg"){ ?>
            <h1>SVG</h1>
        <?php } elseif($method == "png"){ ?>
            <h1>PNG</h1>
        <?php } ?>
            <p>Click the keys to play a little tune!</p>

            <form action="#" method="POST">
                <select id="method" name="method" onchange="this.form.submit()">
                  <option value="svg" <?php if($method == "svg"){ echo "selected"; }?>>SVG - Inline Hyperlinks</option>
                  <option value="png" <?php if($method == "png"){ echo "selected"; }?>>PNG - ImageMap Hyperlinks</option>
                </select> 
            </form>
            
        <?php if($method == "svg"){ ?>
            <svg
           xmlns:dc="http://purl.org/dc/elements/1.1/"
           xmlns:cc="http://creativecommons.org/ns#"
           xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
           xmlns:svg="http://www.w3.org/2000/svg"
           xmlns="http://www.w3.org/2000/svg"
           xmlns:xlink="http://www.w3.org/1999/xlink"
           xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
           xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
           width="600"
           height="500"
           viewBox="0 0 158.75 132.29167"
           version="1.1"
           id="geekgirljoys-playable-keyboard"
           inkscape:version="0.92.0 r15299"
           sodipodi:docname="keyboard.svg"
           inkscape:export-filename="C:\Users\Joy\Desktop\Piano\New\piano.png"
           inkscape:export-xdpi="300"
           inkscape:export-ydpi="300"
           style="enable-background:new">
          <defs
             id="defs12918">
            <linearGradient
               inkscape:collect="always"
               id="linearGradient5259">
              <stop
                 style="stop-color:#003380;stop-opacity:1;"
                 offset="0"
                 id="stop5255" />
              <stop
                 style="stop-color:#003380;stop-opacity:0;"
                 offset="1"
                 id="stop5257" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               id="linearGradient5021">
              <stop
                 style="stop-color:#ffffff;stop-opacity:1;"
                 offset="0"
                 id="stop5017" />
              <stop
                 style="stop-color:#ffffff;stop-opacity:0;"
                 offset="1"
                 id="stop5019" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               id="linearGradient4664">
              <stop
                 style="stop-color:#ffffff;stop-opacity:1"
                 offset="0"
                 id="stop4660" />
              <stop
                 style="stop-color:#000000;stop-opacity:0;"
                 offset="1"
                 id="stop4662" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               id="linearGradient4614">
              <stop
                 style="stop-color:#000000;stop-opacity:1;"
                 offset="0"
                 id="stop4610" />
              <stop
                 style="stop-color:#000000;stop-opacity:0;"
                 offset="1"
                 id="stop4612" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               id="linearGradient15315-5">
              <stop
                 style="stop-color:#f9f9f9;stop-opacity:1;"
                 offset="0"
                 id="stop15311" />
              <stop
                 style="stop-color:#000000;stop-opacity:0.79605263"
                 offset="1"
                 id="stop15313" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               id="linearGradient15157">
              <stop
                 style="stop-color:#333333;stop-opacity:1"
                 offset="0"
                 id="stop15153" />
              <stop
                 id="stop15161"
                 offset="0.5"
                 style="stop-color:#191919;stop-opacity:1;" />
              <stop
                 style="stop-color:#333333;stop-opacity:1"
                 offset="1"
                 id="stop15155" />
            </linearGradient>
            <linearGradient
               inkscape:collect="always"
               xlink:href="#linearGradient15157"
               id="linearGradient15159"
               x1="79.876411"
               y1="325.5043"
               x2="79.886864"
               y2="264.30887"
               gradientUnits="userSpaceOnUse"
               gradientTransform="translate(1.3680627e-7,-79.375004)" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient15315-5"
               id="radialGradient15736"
               cx="38.679722"
               cy="236.95551"
               fx="38.679722"
               fy="236.95551"
               r="12.541217"
               gradientTransform="matrix(5.7072155,0.26868388,-0.01027659,0.21828878,-179.63869,174.83816)"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient4614"
               id="radialGradient4616"
               cx="85.9496"
               cy="328.67267"
               fx="85.9496"
               fy="328.67267"
               r="79.375"
               gradientTransform="matrix(1.7919596,0.01649915,-8.0047577e-4,0.08693941,-62.780617,263.66084)"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient15315-5"
               id="radialGradient4634"
               cx="77.359444"
               cy="176.91103"
               fx="77.359444"
               fy="176.91103"
               r="25.082434"
               gradientTransform="matrix(1.3135871,-0.1191492,0.02348472,0.25891276,-28.413636,140.32382)"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient4664"
               id="radialGradient4666"
               cx="13.091763"
               cy="235.10512"
               fx="13.091763"
               fy="235.10512"
               r="16.501682"
               gradientTransform="matrix(2.2777563,-0.10674805,0.01546079,0.32989785,-20.362998,158.94195)"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5021"
               id="radialGradient5086"
               cx="77.261093"
               cy="169.72464"
               fx="77.261093"
               fy="169.72464"
               r="1.3028055"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5021"
               id="radialGradient5146"
               cx="77.261093"
               cy="169.72464"
               fx="77.261093"
               fy="169.72464"
               r="1.3028055"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5021"
               id="radialGradient5174"
               cx="77.261093"
               cy="169.72464"
               fx="77.261093"
               fy="169.72464"
               r="1.3027751"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5021"
               id="radialGradient5199"
               cx="77.261093"
               cy="169.72464"
               fx="77.261093"
               fy="169.72464"
               r="1.3028055"
               gradientUnits="userSpaceOnUse" />
            <radialGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5021"
               id="radialGradient5239"
               cx="101.47026"
               cy="169.59991"
               fx="101.47026"
               fy="169.59991"
               r="1.3028055"
               gradientUnits="userSpaceOnUse" />
            <linearGradient
               inkscape:collect="always"
               xlink:href="#linearGradient5259"
               id="linearGradient5265"
               x1="-3.1599205"
               y1="235.1051"
               x2="29.343447"
               y2="235.1051"
               gradientUnits="userSpaceOnUse" />
          </defs>
          <sodipodi:namedview
             id="base"
             pagecolor="#ffffff"
             bordercolor="#666666"
             borderopacity="1.0"
             inkscape:pageopacity="0.0"
             inkscape:pageshadow="2"
             inkscape:zoom="1"
             inkscape:cx="239.02174"
             inkscape:cy="369.94902"
             inkscape:document-units="px"
             inkscape:current-layer="layer1"
             showgrid="false"
             units="px"
             showguides="false"
             inkscape:window-width="1680"
             inkscape:window-height="987"
             inkscape:window-x="-8"
             inkscape:window-y="-8"
             inkscape:window-maximized="1" />
          <metadata
             id="metadata12921">
            <rdf:RDF>
              <cc:Work
                 rdf:about="">
                <dc:format>image/svg+xml</dc:format>
                <dc:type
                   rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
                <dc:title></dc:title>
              </cc:Work>
            </rdf:RDF>
          </metadata>
          <g
             inkscape:label="Layer 1"
             inkscape:groupmode="layer"
             id="layer1"
             transform="translate(0,-164.70831)">
            <rect
               style="opacity:1;fill:url(#linearGradient15159);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4.31061602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
               id="keyboad-body"
               width="158.75"
               height="132.29167"
               x="0.26458335"
               y="164.44371"
               rx="0.26458335"
               ry="0.26458335"
               inkscape:export-xdpi="72"
               inkscape:export-ydpi="72" />
               
               
               <a href="http://geekgirljoy.wordpress.com" target="_blank" id="go-go-geekgirljoy">
            <g
               id="geekgirljoy-text">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 style="fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0.70712423;stroke-miterlimit:4;stroke-dasharray:none"
                 transform="matrix(1.1225043,0,0,1.1225043,5.0633408,-92.71991)"
                 id="geekgirljoy-bottom">
                <text
                   xml:space="preserve"
                   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.94135094px;line-height:1.54722679px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0.70712423;stroke-miterlimit:4;stroke-dasharray:none"
                   x="-3.5401669"
                   y="236.54588"
                   id="text5285"><tspan
                     sodipodi:role="line"
                     id="tspan15285-1"
                     x="-3.5401669"
                     y="236.54588"
                     style="fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0.70712423;stroke-miterlimit:4;stroke-dasharray:none">GeekGirlJoy</tspan></text>
                <text
                   id="text5283"
                   y="236.54588"
                   x="-3.5401669"
                   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.94135094px;line-height:1.54722679px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0.70712423;stroke-miterlimit:4;stroke-dasharray:none"
                   xml:space="preserve"><tspan
                     style="fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0.70712423;stroke-miterlimit:4;stroke-dasharray:none"
                     y="236.54588"
                     x="-3.5401669"
                     id="tspan15307-6"
                     sodipodi:role="line">GeekGirlJoy</tspan></text>
              </g>
              <g
                 id="geekgirljoy-top"
                 transform="matrix(1.1225043,0,0,1.1225043,5.0633408,-92.71991)"
                 style="opacity:0.97000002;fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                 inkscape:export-xdpi="72"
                 inkscape:export-ydpi="72">
                <text
                   id="text5247"
                   y="236.54588"
                   x="-3.5401669"
                   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.94135094px;line-height:1.54722679px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                   xml:space="preserve"><tspan
                     style="fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                     y="236.54588"
                     x="-3.5401669"
                     id="tspan5245"
                     sodipodi:role="line">GeekGirlJoy</tspan></text>
                <text
                   xml:space="preserve"
                   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.94135094px;line-height:1.54722679px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
                   x="-3.5401669"
                   y="236.54588"
                   id="text5251"><tspan
                     sodipodi:role="line"
                     id="tspan5249"
                     x="-3.5401669"
                     y="236.54588"
                     style="fill:url(#radialGradient4666);fill-opacity:1;stroke:#003380;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">GeekGirlJoy</tspan></text>
              </g>
            </g>
            </a>
            
            
            <rect
               ry="0.26458335"
               rx="0.26458335"
               y="283.19775"
               x="2.7755576e-017"
               height="13.802217"
               width="158.75"
               id="shading-bottom"
               style="opacity:1;fill:url(#radialGradient4616);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.39234722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
               inkscape:export-xdpi="72"
               inkscape:export-ydpi="72" />
            <rect
               style="opacity:0.95999995;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#182943;stroke-width:4.23333339;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
               id="keys-background"
               width="96.388542"
               height="95.16375"
               x="30.018394"
               y="189.01839"
               rx="0.26458332"
               ry="0.26458332"
               inkscape:export-xdpi="72"
               inkscape:export-ydpi="72" />
               
            <a href="#" id="Key-B">   
            <g
               id="white-key-b"
               transform="translate(0,-0.56104268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="b-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-80.626374,-672.05687)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="b-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="b-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="b-text"
                 y="276.75943"
                 x="117.51627"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="117.51627"
                   id="tspan4668-6-9"
                   sodipodi:role="line">B</tspan></text>
            </g>
            </a> 
            <g
               id="keyboard-text">
              <text
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="keyboard-bottom"
                 y="179.79259"
                 x="51.96806"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.88270187px;line-height:3.09445357px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#f9f9f9;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
                 xml:space="preserve"><tspan
                   style="fill:#f9f9f9;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
                   y="179.79259"
                   x="51.96806"
                   id="tspan15285"
                   sodipodi:role="line">Keyboard</tspan></text>
              <text
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 xml:space="preserve"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:11.88270187px;line-height:3.09445357px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient4634);fill-opacity:1;stroke:none;stroke-width:0.12377814"
                 x="51.96806"
                 y="179.79259"
                 id="keyboard-top"><tspan
                   sodipodi:role="line"
                   id="tspan15307"
                   x="51.96806"
                   y="179.79259"
                   style="fill:url(#radialGradient4634);fill-opacity:1;stroke-width:0.12377814">Keyboard</tspan></text>
            </g>
            
            <a href="#" id="Key-C" name="Key-C"> 
            <g
               id="white-key-c">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-164.17119,-672.61793)"
                 id="c-rect-group">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.19712651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="c-grey-rect"
                   width="3.9700837"
                   height="1.9451796"
                   x="59.26228"
                   y="289.87738"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="c-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="c-text"
                 y="276.7594"
                 x="33.866669"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.7594"
                   x="33.866669"
                   id="tspan4668"
                   sodipodi:role="line">C</tspan></text>
            </g>
            </a> 
            
            <a href="#" id="Key-D"> 
            <g
               id="white-key-d"
               transform="translate(0,-0.14374268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="d-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-150.17727,-672.47417)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="d-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="d-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="d-text"
                 y="276.75943"
                 x="47.997005"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="47.997005"
                   id="tspan4668-6"
                   sodipodi:role="line">D</tspan></text>
            </g>
            </a>
            
            
            <a href="#" id="Key-E"> 
            <g
               id="white-key-e"
               transform="translate(0,-0.19166268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="e-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-136.30317,-672.42625)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="e-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="e-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="e-text"
                 y="276.75943"
                 x="61.623047"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="61.623047"
                   id="tspan4668-6-7"
                   sodipodi:role="line">E</tspan></text>
            </g>
            </a>
            
            <a href="#" id="Key-F"> 
            <g
               id="white-key-f"
               transform="translate(0,-0.33544268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="f-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-122.30925,-672.28247)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="f-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="f-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="f-text"
                 y="276.75943"
                 x="75.976692"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="75.976692"
                   id="tspan4668-6-3"
                   sodipodi:role="line">F</tspan></text>
            </g>
            </a>
            
            <a href="#" id="Key-G"> 
            <g
               id="white-key-g"
               transform="translate(0,-0.36934268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="g-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-108.4944,-672.24857)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="g-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="g-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="g-text"
                 y="276.75943"
                 x="89.272003"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="89.272003"
                   id="tspan4668-6-73"
                   sodipodi:role="line">G</tspan></text>
            </g>
            </a>
            
            <a href="#" id="Key-A"> 
            <g
               id="white-key-a"
               transform="translate(0,-0.51312268)">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 id="a-rect-group"
                 transform="matrix(3.2767822,0,0,3.2767822,-94.50048,-672.10479)">
                <rect
                   style="opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.20480227;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="a-grey-rect"
                   width="3.9700634"
                   height="1.970214"
                   x="59.26228"
                   y="289.85236"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="a-white-rect"
                   width="3.9781194"
                   height="27.495825"
                   x="59.26228"
                   y="262.95197"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="a-text"
                 y="276.75943"
                 x="104.02252"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;stroke-width:0.26458335"
                   y="276.75943"
                   x="104.02252"
                   id="tspan4668-6-6"
                   sodipodi:role="line">A</tspan></text>
            </g>
            </a>
            
            
            <a href="#" id="Key-C-Sharp"> 
            <g
               id="black-key-c-sharp">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-205.38614,-673.39341)"
                 id="c-sharp-rect-group">
                <rect
                   style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.79170525;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="c-sharp-grey-rect"
                   width="2.6989212"
                   height="1.2514575"
                   x="74.291664"
                   y="280.27954"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66028059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="c-sharp-black-rect"
                   width="2.6957428"
                   height="17.689808"
                   x="74.291664"
                   y="262.95673"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="c-sharp-text"
                 y="243.509"
                 x="38.438705"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;fill:#ffffff;stroke-width:0.26458335"
                   y="243.509"
                   x="38.438705"
                   id="tspan4668-2"
                   sodipodi:role="line">C#</tspan></text>
            </g>
            </a>
            
            
            <a href="#" id="Key-D-Sharp"> 
            <g
               id="black-key-d-sharp">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-189.99357,-673.39346)"
                 id="d-sharp-rect-group">
                <rect
                   style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.79805452;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="d-sharp-grey-rect"
                   width="2.6988971"
                   height="1.2716219"
                   x="74.291664"
                   y="280.25937"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66028059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="d-sharp-black-rect"
                   width="2.6957428"
                   height="17.689808"
                   x="74.291664"
                   y="262.95673"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="d-sharp-text"
                 y="243.509"
                 x="53.773075"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;fill:#ffffff;stroke-width:0.26458335"
                   y="243.509"
                   x="53.773075"
                   id="tspan4668-2-2"
                   sodipodi:role="line">D#</tspan></text>
            </g>
            </a>
            
            
            <a href="#" id="Key-F-Sharp"> 
            <g
               id="black-key-f-sharp">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-163.56119,-673.39346)"
                 id="f-sharp-rect-group">
                <rect
                   style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.79805452;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="f-sharp-grey-rect"
                   width="2.6988971"
                   height="1.2716219"
                   x="74.291664"
                   y="280.25937"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66028059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="f-sharp-black-rect"
                   width="2.6957428"
                   height="17.689808"
                   x="74.291664"
                   y="262.95673"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="f-sharp-text"
                 y="243.509"
                 x="80.059036"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;fill:#ffffff;stroke-width:0.26458335"
                   y="243.509"
                   x="80.059036"
                   id="tspan4668-2-1"
                   sodipodi:role="line">F#</tspan></text>
            </g>
            </a>
            
            
            
            <a href="#" id="Key-G-Sharp"> 
            <g
               id="black-key-g-sharp">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-148.92173,-673.39346)"
                 id="g-sharp-rect-group">
                <rect
                   style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.79805452;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="g-sharp-grey-rect"
                   width="2.6988971"
                   height="1.2716219"
                   x="74.291664"
                   y="280.25937"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66028059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="g-sharp-black-rect"
                   width="2.6957428"
                   height="17.689808"
                   x="74.291664"
                   y="262.95673"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="g-sharp-text"
                 y="243.10257"
                 x="94.651955"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;fill:#ffffff;stroke-width:0.26458335"
                   y="243.10257"
                   x="94.651955"
                   id="tspan4668-2-4"
                   sodipodi:role="line">G#</tspan></text>
            </g>
            </a>
            
            
            
            <a href="#" id="Key-A-Sharp"> 
            <g
               id="black-key-a-sharp">
              <g
                 inkscape:export-ydpi="72"
                 inkscape:export-xdpi="72"
                 transform="matrix(3.2767822,0,0,3.2767822,-133.19786,-673.39346)"
                 id="a-sharp-rect-group">
                <rect
                   style="opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.79805452;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="a-sharp-grey-rect"
                   width="2.6988971"
                   height="1.2716219"
                   x="74.291664"
                   y="280.25937"
                   rx="0.08074487"
                   ry="0.08074487" />
                <rect
                   style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66028059;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
                   id="a-sharp-black-rect"
                   width="2.6957428"
                   height="17.689808"
                   x="74.291664"
                   y="262.95673"
                   rx="0.08074487"
                   ry="0.08074487" />
              </g>
              <text
                 id="a-sharp-text"
                 y="243.509"
                 x="110.64803"
                 style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444447px;line-height:6.61458349px;font-family:Pacifico;-inkscape-font-specification:Pacifico;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458335;enable-background:new"
                 xml:space="preserve"><tspan
                   style="font-size:5.64444447px;fill:#ffffff;stroke-width:0.26458335"
                   y="243.509"
                   x="110.64803"
                   id="tspan4668-2-5"
                   sodipodi:role="line">A#</tspan></text>
            </g>
            </a>
            
            
            
            
            <path
               d="m 78.034761,170.34857 -0.718473,-0.10878 -0.67912,0.25852 0.10877,-0.71847 -0.258513,-0.67913 0.718473,0.10878 0.679121,-0.25852 -0.108771,0.71847 z"
               inkscape:randomized="0"
               inkscape:rounded="0"
               inkscape:flatsided="false"
               sodipodi:arg2="1.4640607"
               sodipodi:arg1="0.67866249"
               sodipodi:r2="0.51810318"
               sodipodi:r1="0.99390382"
               sodipodi:cy="169.72464"
               sodipodi:cx="77.261093"
               sodipodi:sides="4"
               id="flare-1"
               style="opacity:0.644;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient5174);stroke-width:1.0582726;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill;enable-background:new"
               sodipodi:type="star"
               transform="matrix(2.1681284,0,0,0.50590109,-110.80528,84.48127)" />
            <path
               d="m 78.034761,170.34857 -0.718473,-0.10878 -0.67912,0.25852 0.10877,-0.71847 -0.258513,-0.67913 0.718473,0.10878 0.679121,-0.25852 -0.108771,0.71847 z"
               inkscape:randomized="0"
               inkscape:rounded="0"
               inkscape:flatsided="false"
               sodipodi:arg2="1.4640607"
               sodipodi:arg1="0.67866249"
               sodipodi:r2="0.51810318"
               sodipodi:r1="0.99390382"
               sodipodi:cy="169.72464"
               sodipodi:cx="77.261093"
               sodipodi:sides="4"
               id="flare-2"
               style="opacity:0.644;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient5146);stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill;enable-background:new"
               sodipodi:type="star"
               transform="matrix(1,0,0,0.68256474,-14.497777,54.437717)" />
            <path
               d="m 78.034761,170.34857 -0.718473,-0.10878 -0.67912,0.25852 0.10877,-0.71847 -0.258513,-0.67913 0.718473,0.10878 0.679121,-0.25852 -0.108771,0.71847 z"
               inkscape:randomized="0"
               inkscape:rounded="0"
               inkscape:flatsided="false"
               sodipodi:arg2="1.4640607"
               sodipodi:arg1="0.67866249"
               sodipodi:r2="0.51810318"
               sodipodi:r1="0.99390382"
               sodipodi:cy="169.72464"
               sodipodi:cx="77.261093"
               sodipodi:sides="4"
               id="flare-3"
               style="opacity:0.644;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient5199);stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill;enable-background:new"
               sodipodi:type="star"
               transform="matrix(1,0,0,0.68256474,-8.203631,68.866748)" />
            <path
               d="m 78.034761,170.34857 -0.718473,-0.10878 -0.67912,0.25852 0.10877,-0.71847 -0.258513,-0.67913 0.718473,0.10878 0.679121,-0.25852 -0.108771,0.71847 z"
               inkscape:randomized="0"
               inkscape:rounded="0"
               inkscape:flatsided="false"
               sodipodi:arg2="1.4640607"
               sodipodi:arg1="0.67866249"
               sodipodi:r2="0.51810318"
               sodipodi:r1="0.99390382"
               sodipodi:cy="169.72464"
               sodipodi:cx="77.261093"
               sodipodi:sides="4"
               id="flare-4"
               style="opacity:0.644;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient5086);stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
               sodipodi:type="star"
               transform="matrix(1,0,0,0.68256474,0,53.630995)" />
            <path
               sodipodi:type="star"
               style="opacity:0.644;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#radialGradient5239);stroke-width:1.0583334;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
               id="flare-5"
               sodipodi:sides="4"
               sodipodi:cx="101.47026"
               sodipodi:cy="169.59991"
               sodipodi:r1="0.99390382"
               sodipodi:r2="0.51810318"
               sodipodi:arg1="0.67866249"
               sodipodi:arg2="1.4640607"
               inkscape:flatsided="false"
               inkscape:rounded="0"
               inkscape:randomized="0"
               d="m 102.24393,170.22384 -0.71847,-0.10877 -0.67912,0.25851 0.10877,-0.71847 -0.25852,-0.67912 0.71848,0.10877 0.67912,-0.25851 -0.10877,0.71847 z"
               transform="matrix(1,0,0,0.74845571,0,42.467279)" />
          </g>
        </svg>

            
        <?php } elseif($method == "png"){ ?>
            
            <img src="keyboard.png" align="middle" usemap="#keyboardmap">

                <map name="keyboardmap">
                  <area id="go-go-geekgirljoy" alt="go-go-geekgirljoy" title="go-go-geekgirljoy" shape="rect" coords="0,0,148,48" target="_blank" href="http://geekgirljoy.wordpress.com" >
                  <area id="Key-C" alt="" title="" href="#" shape="poly" target="_self" coords="115,93,115,433,163,433,164,319,145,318,145,93" />
                  <area id="Key-D" alt="" title="" href="#" shape="poly" target="_self" coords="178,93,179,319,167,319,167,433,217,433,217,319,202,319,203,93" />
                  <area id="Key-E" alt="" title="" href="#" shape="poly" target="_self" coords="236,93,236,319,219,319,220,434,269,434,268,93" />
                  <area id="Key-F" alt="" title="" href="#" shape="poly" target="_self" coords="272,93,272,434,322,434,322,320,303,320,302,93" />
                  <area id="Key-G" alt="" title="" href="#" shape="poly" target="_self" coords="336,93,336,320,324,321,324,434,374,434,374,320,357,319,358,93" />
                  <area id="Key-A" alt="" title="" href="#" shape="poly" target="_self" coords="392,93,392,319,378,319,378,433,428,433,427,319,418,319,418,93" />
                  <area id="Key-B" alt="" title="" href="#" shape="poly" target="_self" coords="451,93,451,319,430,320,430,433,479,433,479,93" />
                  <area id="Key-C-Sharp" alt="" title="" href="#" shape="poly" target="_self" coords="146,93,146,308,178,308,178,93" />
                  <area id="Key-D-Sharp" alt="" title="" href="#" shape="poly" target="_self" coords="204,92,204,308,236,308,236,93" />
                  <area id="Key-F-Sharp" alt="" title="" href="#" shape="poly" target="_self" coords="304,93,304,308,336,308,336,93" />
                  <area id="Key-G-Sharp" alt="" title="" href="#" shape="poly" target="_self" coords="360,92,359,308,392,308,391,93" />
                  <area id="Key-A-Sharp" alt="" title="" href="#" shape="poly" target="_self" coords="419,93,420,309,451,308,450,93" />
                </map>
        <?php } ?>

        </div>


        <script>
          document.getElementById("Key-C").addEventListener("click", function () {document.getElementById("C-Audio").play(); });
          document.getElementById("Key-D").addEventListener("click", function () {document.getElementById("D-Audio").play(); });
          document.getElementById("Key-E").addEventListener("click", function () {document.getElementById("E-Audio").play(); });
          document.getElementById("Key-F").addEventListener("click", function () {document.getElementById("F-Audio").play(); });
          document.getElementById("Key-G").addEventListener("click", function () {document.getElementById("G-Audio").play(); });
          document.getElementById("Key-A").addEventListener("click", function () {document.getElementById("A-Audio").play(); });
          document.getElementById("Key-B").addEventListener("click", function () {document.getElementById("B-Audio").play(); });
          document.getElementById("Key-C-Sharp").addEventListener("click", function () {document.getElementById("C-Sharp-Audio").play(); });
          document.getElementById("Key-D-Sharp").addEventListener("click", function () {document.getElementById("D-Sharp-Audio").play(); });
          document.getElementById("Key-F-Sharp").addEventListener("click", function () {document.getElementById("F-Sharp-Audio").play(); });
          document.getElementById("Key-G-Sharp").addEventListener("click", function () {document.getElementById("G-Sharp-Audio").play(); });
          document.getElementById("Key-A-Sharp").addEventListener("click", function () {document.getElementById("A-Sharp-Audio").play(); });
        </script>


    </body>
</html>

 

If you have any questions please leave them in the comments.

If you would like to get a copy of this entire project’s code and assets you can get a copy over on GitHub here.

Please Like, Comment & Share my posts with your friends and followers on social media.

If you would like to suggest a topic or project for an upcoming post feel free to contact me.

If you found this article useful or want to help me grow consider supporting me over on Patreon.

With that, have a great week & I will see you all in the next post!

Much Love,

~Joy

Blog at WordPress.com.

Up ↑