3/04/2017

Text-To-Speech: Problem where TTS voice stops or never starts in Chrome / Windows bug

Well, I wasted a couple of days trying to figure out what was wrong with my awesome TTS program stopped working around the end of 2016 or beginning of 2017.

I thought maybe I had a competing script interfering with it, so I wrapped it in a namespace, and same problem.

Then I tried just cutting it down to the bare minimum, and sometimes it would work, but it would stop after about 2 sentences. And if it was more than a paragraph, the whole thing would work at all. It's very frustrating and disappointing to me, because I really want to make engaging Speech and Speech Recognition programs. But this is a total failure.

Except, it wasn't.

The problem is on the latest Windows 10 version of Chrome (). Everything works fine on my iPhone, on my Android phone, on my iMac, and on Windows 10 in Firefox and MS Edge and Opera.

So, what then .... Google is having a failure. The bugs have been reported to Chrome Bug Report, but no movement on the fix yet. They're kind of pessimistic about it even being a problem, from what I can read there. C'mon Google / Chromium team -- you're the best in the world. Get it fixed! xo

This script demonstrates the problem.

<html>
<head>
<script>
var synth = window.speechSynthesis;
var ttsStart = function () {
console.log("starting");
var myText = document.getElementById("myTextArea").value;
var utterThis = new SpeechSynthesisUtterance(myText);
synth.speak(utterThis);

utterThis.onstart = function(event) {
console.log('We have started uttering this speech: ' + event.utterance.text);
}
utterThis.onend = function (event) {
console.log("[Utterance ended]");
}
}
var ttsCancel = function () {
window.speechSynthesis.cancel();
}
</script>
</head>
<body>
<textarea id="myTextArea" cols="50" rows="15">
Up until about the end of 2016, or maybe in early 2017, Windows Chrome TTS functionality stopped working the way it used to. 
If you will notice, it stops around 200 or 300 characters even though the documentation says 32,768 characters is the 
maximum limit. On my PC browser, the text will have stopped being read before this point. And you would need to hit 
the Cancel button to reset the utterance because it is just hanging for no apparent reason. Longer passages, just under 
1400 characters, do not read aloud at all. Please fix, please because I love TTS so much. Thanks!</textarea><br />
<button id="start" onclick="ttsStart()">Start</button> <button id="cancel" onclick="ttsCancel()">Cancel</button> 

</body>
</html>

2/14/2017

MIT App Inventor 2: Tips and Tricks

I just started developing with the MIT App Inventor.

I love it!

How I didn't know about this till today, I do not know. I'm taking a class with ShawAcademy this month, and they've moved from using jQuery Mobile, PhoneGap and Android Studio to this much simpler, and FREE starter from the brains at MIT.

MIT App Inventor is an Android-only development tool. And, before 3 or 4 months ago I didn't own any kind of Android device. This is my first foray into Google Apps and ... I think this is gonna work out great!

Apparently, App Inventor has been around since, like, 2010 or 2011. This is the 2nd version of the software, yet it's still in Beta mode. There does seem to support out there on the web -- with tutorials and documentation, but much of it is not specific enough, or it is in a foreign language.

So, I'm just going to gather some notes here. Because I'm running into a wall on some of the things I want to do.

#1. Display formatted HTML inside the App.


I want to download some text from my company website, and then show it inside the app's as formatted HTML.

Two ways to display HTML in App Inventor.

  1. Use a Label object. Set it to:
    [x] HTML Format.
    Width [fill parent].
    Height [whatever you like].
  2. Use the WebViewer object.
    Defaults are probably fine.
To get the information from an external site:
  • Use a Connectivity > Web object.
To store the information to a file, you need to:
  • Use a Storage > File object.

Now, there seems to be a thing with the file paths, that is causing me so much problem. 

I'm using an older LG phone from FreedomPop. It was inexpensive and I just wanted a testing device. It's not the fastest thing and the version of Android on it is getting older, with no hope of being upgraded.

I created a Variable to hold a filename for later use: filenameToSave = "testFile1.html"

And I created another Variable to describe the file path: testingFilePath = "......."

The dots is where I had the problem. What should the dots be? Different pages on the web say different things from different years and different situations. Most examples seem to be suggesting that a "developer" variable be created and set to "TRUE". 

Why? There seems to be a difference in the way that files are handled in App Inventor with regard to testing and an actual app that has been packaged and posted online. 

I had to go onto my phone and find the File Manager app, to figure out the correct file path on my LG. It turned out to be:

     "file:///storage/emulated/0/AppInventor/data/". 

Now the pre-pended "file://" is very important apparently, or the WebViewer object will not recognize the file as a legitimate location. You'd think you could just use the filename "testFile1.html" or maybe "/testFile1.html" or even "./testFile1.html". But, alas, no. The only way I could get it to work was with the full path name and the "file://" protocol at the beginning. 

Here's what the MIT App Inventor page has to say about it, which didn't work for me for testing.

 The default behavior is to write files to the private data directory associated with your App. The Companion writes files to /sdcard/AppInventor/data for easy debugging. If the file path starts with a slash (/), then the file is created relative to /sdcard. For example, writing a file to /myFile.txt will write the file in /sdcard/myFile.txt.

Another developer remarked:
I found what was wrong with me. I included FULL path, such as "/mnt/sdcard/AppInventor/data/ABC.txt" or "/emulator/storage/0/AppInventor/data/ABC.txt"
Instead, as Steve shows, I changed it to "/Takafile/ABC.txt"  or  "/AppInventor/data/ABC.txt" then both work.

Still new to this, so, I don't know all the ins and outs yet. These are just notes.

LINKS:

Free tutorial book (Online HTML)

23andMe: I got my Genetic Test Results -- Surprise!

In December of 2016, I ordered a genetic test kit from 23andMe.

I ordered the Ancestry report, though I was also interested in looking for health markers. However, the Ancestry report was $99, and I discovered before ordering that 23andMe was prevented from most diagnostic health analysis by the U.S. government. It seems there are some markers that are very strong indicators of a person being a "Carrier" of a condition through hereditary means, but other genetic markers are unclear. Fortunately, 23andMe provides a solution for this, of sorts -- "raw data" downloads.

[UPDATE: FDA Approves 10 Genetic Tests for 23andMe -- see below.] 

I got the test kit in about a week, or maybe less. It was a small white box with a couple of instructions in it. A plastic bag. And a plastic test tube with a flip cap on top of it. The flip cap had a liquid in it and a membrane holding the liquid inside.

The instructions said to fill the vial up to a certain line. I don't know why so many people complain about this step. Really it wasn't that much saliva. It only took a minute. Once it is at the fill line, you are supposed to close the flip cap until the membrane snaps and the liquid drops down. The liquid did not drop down on my sample very well, so I had to coax it out with a loosening of the lid and re-tightening. Then you shake it up, and put it in the plastic bag. 


The 2nd component of the setup process is to register at the 23andMe website. It doesn't appear that the person ordering the kit has to have anything to do with the registration name or ID. But it does ask for your name and some other information. I forget. There are privacy concerns associated with this type of testing -- we are entering a whole different era of uncertainty. But I think I've already gotten the brunt of my genetic health concerns, so, who cares?!? Once you match the special test kit number to the 23andMe database registry, you're all set. Seal up the box, and stick it in the mailbox.

Then you wait.... And wait... And, other than a couple of emails, it takes about 5 or 6 weeks. I sent mine in the first week of January and got the test results in the first half of February. I found them before I got the confirmation email. There is a sort of progress bar on the site that shows you what is happening with your tests, but it just kind of hangs after the first week. Anyway, I got it. Woo hoo!

My ancestry is mostly what I expected, but not exactly. The website shows you a few different charts that don't make sense at first, but after a bit of analysis and interaction, it becomes clear. 

The first is this pie chart and map. 


The pie chart colors match the colors on the map. And the size of the slices represents the percentage of each color on the map. So, the majority of my ethnicity is European! Only by a couple of points though. Most of that is British-Irish (mom always said Scottish & Irish), and French-German (mom always said her grandmother had some German in her family, and that she was gruff and kind of mean. Haha. They tend to live into their late 80s. There was some Broadly European on there.

The other side is my father, who came to the States from the Philippines via a U.S. Navy recruitment program. I'm not close with that half of the family, in large part beause of the distance. I've only met a few relatives from there. One just died. They all seem to live into their 90s. The only other thing I know is that my grandfather on that side was Chinese. Or so I thought. According to 23andMe, I'm only about 6% Chinese, and the rest is mostly Southeast Asian. It seems the Pacific Islanders are not separate from the Vietnamese or Laotians or whatever else lives in the lower Far East.

What I am not is Japanese, Korean, Australian aboriginal, Eastern European, Northern European or Southern European, North African or Middle Eastern; nor am I an Iberian (which seems to be the marker for Spanish ancestry). I thought the latter might show up because the Spanish occupied the Philippines in the 1600s. Perhaps, that extra 2% represents the Spanish component -- who can say for sure?



The are a few tiny surprises.

1) A Native American ancestor. Supposedly lived in the 1700s. Now, this is unexpected -- welcomed, but how odd that it's less than 1%, and 23andMe seems so certain about it. "All we can tell you is what the tests indicate," they say. The sort of funny thing about Native Americans is that they fall under the Asian category. One assumes that this is from the theory that American Indians came from Asians who crossed the Alaskan Land Bridge and moved south for thousands of years.

2) A South Asian -- this would be from the country of India, as opposed to American Indian. Or perhaps Pakistani, or Bangladeshi. No way to know.

3) One tiny smidge of African. I love it. Really, I don't have to be disappointed and say, I have zero-point-zero percent recent African ancestry. Nope: 0.1 percent, thank you..


There are some other aspects of the 23andMe test -- Neanderthal Ancestry, and Haplotypes. I can't say I understood much about these two. Apparently, ancient humans mixed with neanderthals to a small degree, while they were coexisting in the Middle East region. So, they have a way to test for Neanderthal roots. And mine appears to be less than others. The only signal I seem to inherit from them, it to have a less hair back -- yay. The Haplotypes give a sort of pathway back through the weave of human tapestry. A single thread traces back like 15,000 or 20,000 years. And mine seems to go back as far as the Near East. This means that I and many other people are direct descendants of someone who once lived in the Near East. There are different ways to trace this on the mothers side from mitochondrial mutations, and in the father from the Y chromosome. Mmmmokay. 

This begs the question: Why does the genetic test only go back 200 or 300 years, when anyone who believes in science to any degree understands that we descended from early human-like creatures, and they descended from early ape-type creatures, and they descended from some type of small mammal, and they descended from some type of amphibian, from some type of fish, from some type of very basic one-celled creature. We all started the same, wherever you want to define the beginning of humanity.

So.... I dunno. I guess, part of me wanted to see more -- to know more. To have an animation show me how my family might have migrated around the world. I can only trace the mother and father -- and they are from opposite sides of the earth. I can only imagine that the next couple of generations will have even more mixed up DNA. My nieces, for instance have a Puerto Rican mom, so, wow! Would love to see their mix. I'm happy I did the test, but want more.

The website does allow registered owners to answer a whole lot of questions as a volunteer for research. They also allow you to see your distant relatives. This, again, is a privacy and security risk for reasons that have yet to emerge in the tech world. I suppose my genetics will escape and be out on the internet for ever soon. Heck, I may even post my own ZIP download of my raw data some day. I don't really care that much. Nothing to hide. Genes are genes. You don't get to choose them -- though, you can choose to alter them now, thanks to CRISPR. Yoinks!

I did take the raw data and uploaded it to Promethease.com. And for $5 more, I got another ZIP download that included a HTML web site that can be browsed on my own computer privately. They say they do allow your to see your data online for 45 days, but that they intend to delete all data, but no guarantees. Again, who cares. The Promethease analysis mostly matches the 23andMe markers against known generic variants and markers. The strongest one said I have the lowest risk for Alzheimer's. The 2nd strongest one said I'm at risk for male pattern baldness. Gee, too late. Interesting that it said that, though. There were lots of other indicators both good and not so good. Many of the things it touched on are known to my family, though some are not at all. 

The problem with knowing this stuff, I suppose, is that this subjects you to having "pre-existing conditions" which make it really hard to get healthcare coverage here in the U.S.A. We currently have Obamacare / The Affordable Care Act which mercifully prevents insurance companies from excluding people who have had illnesses. But, now we don't have Obama anymore, and Master Cheeto has put into place every manner of antagonist against fairness and equality and access for healthcare and business and education. Don't let me get started.... 

All-in-all, I LOVE THE 23andMe TEST RESULTS. 

Seriously, get it done. It's super. And a gift of knowledge for both me and my family.


UPDATE: 3 months later 

On April 7, it was announced that 23andMe was finally approved for 10 tests to "assess genetic risks" for:
  • Parkinson's disease
  • Alzheimer's (late onset)
  • Celiac disease
  • Alpha-1 antitrypsin deficiency
  • Primary dystonia (early onset)
  • Factor XI deficiency
  • Gaucher disease type 1
  • Glucose-6-phosphate dehydrogenase deficiency
  • Hereditary hemochromatosis
  • Hereditary thrombohilia

The first three sound most appealing to the broadest user base. I don't know if that means I have to get tested again. Or if I would need to pay the extra $99 to get the additional set of health test results. I don't think I have any of them, but I'm sure it's a bargain for people who do have reason for concern.

The other thing I learned last month was:

I'm related to British Royalty!

I looked up the maternal haplogroup -- J1c2c. It's a mitochondrial mutation that is passed along the maternal side of the family tree. The last two Kings of England, who were from the Plantagenet dynasty, were brothers. King Richard III was killed in battle and, whatever is true about his time as ruler, his body was found a couple of years ago, and genetic testing was done. My haplogroup is closely related to his mother, and grandmother, and great grandmother, etc. So, at some early point, I was a member of the Plantagenet lineage, but not directly related to Richard, because he had a specifc mutation -- J1c2c3. It was exciting for a day. But since neither he, nor his brother had any children, it's not like my mom's family would have been direct descendents of the throne. [Whomp-whomp.] 

Anyway, fun info -- I never would have known. Get your own 23andMeTest.

12/16/2016

Why I am doing 23andme Genetic Sequencing & Testing

Okay, I'm totally paranoid about this. But actually more curious than anything. So, here goes....

23andme is a company that does genetic sequencing. For $99, they will do an Ancestry analysis. Or for $199, they will also do a Wellness and Traits analysis.

Click this link and I'll get a small reward from 23andme if you buy a service. Thanks!!!

23andme

Why do I want to hand my DNA over to some database?


I don't like the idea of it all that much, but I've got a good reason.

I'm seriously wondering if I have a specific health condition that there are genetic markers for. Now, 23andme is prohibited by US Law from making claims or performing services related to broad health claims. So, they stick to the Ancestry and Wellness mostly.

However, the brilliant thing that they do -- and they should do, too -- is that they provide a download link for "Raw Data." They do make you agree to a sweeping statement that says the info they provide, while tested, is not considered accurate or useful for health analysis.

So, yeah.

Why not get this done by a doctor or lab?


I could get the test done by my doctor -- but he's difficult. I could pay $140 and get a definitive answer from LabCorp. But then I'd only be getting info about that one thing.

For less money, I get "Raw Data" about much of my genome, which sounds really interesting to me.

You might say, "Well, they can't possibly give you your entire genetic sequencing -- that'd be huge." And for now, that's correct. They seem to do a sample of genes known for one reason or another.

And you might say, "So, what do you do with the data. It's just data. It's not meaningful information unless you know what you're looking at." And you'd be correct again.

So, there's another separate service called Promethease.com. And at Promethease, you can upload your "Raw Data" and then fiddle with a lot of switches and knobs, and then the site will match your genetic markers to a database of known variants (or something like that).

You might ask, "Is there any other services like this that might be free or less money?" I don't know for sure. 23andme came up in conversation -- I'm old. I have little to lose (today) by doing this (I hope).


Again, click this link and I'll get a referral reward when you decide to join me. Yay!

BUY YOUR OWN KIT AT 23andme

10/25/2016

Linux / Apache -- Notes on Logrotate, Apache logs not rotating

I've got a problem with logrotate, a program on Ubuntu Linux, which is supposed to rotate the many log files.

Normally, log files are just text files that are appended with more lines of text whenever a specific event occurs. Rotation of log files means that the text files are periodically maintained and archived so that they don't get too big.

For Apache web server, there are a couple of log files (located in the /log/ folder just above the public directory) --
access.log
error.log

When these files are rotated, they will be archived under new files that look like this:

access.log.1
access.log.2
error.log.1
error.log.2

The log rotation is usually part of 3 maintenance setups located in the following directories;
/etc/cron.daily
/etc/cron.weekly
/etc/cron.monthly

These will be run from a cronjob with commands that look like this:
17 *    * * *   cd / && run-parts --report /etc/cron.hourly
25 6    * * *   ( cd / && run-parts --report /etc/cron.daily ) | mail -s "cron daily" me@myemail.comnet
47 6    * * 7   ( cd / && run-parts --report /etc/cron.weekly ) | mail -s "cron weekly" duy@me@myemail.comnet
52 6    1 * *   ( cd / && run-parts --report /etc/cron.monthly ) | mail -s "cron monthly" me@myemail.comnet

Another cronjob can be added to directly run logs separately from the daily crons (but the logrotate command might need to be specified with its path:
20 17 23 * * /usr/sbin/logrotate /etc/logrotate.conf

A status file shows the date when each log was last updated:
/var/lib/logrotate/status

There are configuration files located inside the directory:
/etc/logrotate.d

One of these is the /apache file. It will contain commands that may look like this:
/path/to/my/log/*.log {
        weekly
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 root adm
        # CHANGE THIS SETTING IF PERMISSIONS ARE NOT CORRECT
        # su myusername mygroupname
        sharedscripts
        postrotate
                if /etc/init.d/apache2 status > /dev/null ; then \
                    /etc/init.d/apache2 reload > /dev/null; \
                fi;
        endscript
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi; \
        endscript
}






9/11/2016

Games: 2-D Gaming Math

Just some notes on game creation. This is a post that will grow as I learn more.

I'm using Javascript examples here.

----

2-D Game Basics


2-D gaming exists on a plane.

The plane will have dimensions of width and height. Width is referred to as variable "x" and height is referred to as "y".

A typical display on a computer screen will refer to positions on a grid in a left-to-right and top-to-bottom manner. That means that the top-left corner pixel of the screen or canvas will be at (0,0). Higher x numbers will move the reference to the right, and higher y numbers will move the reference down.

Negative numbers will typically refer to values that are either above or to the left of the screen or canvas, and are typically unseen or off-screen. The same goes for values that are larger than the x and y  dimensions of the canvas or screen.

So, moving across space on the plane means you would add or subtract values for x and y.

x = x + 1; // Moves right
x = x -1; // Moves left
y = y + 1; // Moves down
y = y -1; // Moves up

-----

Distance Between Two Points on a Plane


Using two points at (x1,y1) and (x2,y2), you can determine the distance between two points by using this formula:

distance = Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));

This is the same as A^2 + B^2 = C^2 -- also refers to the hypotenuse of a right triangle. Note that Javascript does not use the carat notation for powers.

-----


How to Move Diagonally Toward a Specific Target Point?


You might be happy with moving just up and down, or left and right, or you might want to move diagonally. However, if you want to move the equivalent of 1 unit distance in a diagonal manner, you cannot do so simply by adding 1 to both x & y, because you will then be moving further than 1 unit. In terms of trigonometry and a 45 degree angle.

Wrong Formula for Moving 1 Unit Diagonally


Math.sqrt( Math.pow(1,2) + Math.pow(1,2)) = 1.4142;

// SQUARE ROOT OF 2 IS NOT 1 UNIT DISTANCE

So, you need to use a different formula that will instead measure the 1 unit distance around the point of origin -- like you were drawing a circle on grid paper using a compass or a pencil and a piece of thread.

Formula to Move Diagonally Toward an Object


this refers to the current object.

target would be object we want to move toward.

velocity represents the distance that we want to move away from a location. (Ex. 2 would be faster than 0.5.)

// DETERMINE WHAT DIFFERENCES ARE BETWEEN X & Y
// (AKA ADJACENT AND OPPOSITE SIDES OF A TRIANGLE)
// AND IF THEY ARE POSITIVE OR NEGATIVE
directionX = (target.x - this.x);
directionY = (target.y - this.y);

// USE TRIGONOMETRIC ARCTANGENT TO GET THE ANGLE
// USING THE SIDE MEASURMENTS OF THE TRIANGLE
angle = Math.atan(directionY, directionX);

// USE TRIGONOMETRIC SINE AND COSINE TO GET A POSITIVE OR NEGATIVE
// VALUE OF THE DISTANCE OF THE NEW LOCATION
velocityX = this.velocity * Math.cos(angle);
velocityY = this.velocity * Math.sin(angle);

// CHANGE VALUE OF THE CURRENT POSITION OF X & Y
// BY ADDING THE DETERMINED VALUES
this.x += velocityX;
this.y += velocityY;

Difference Between Degrees and Radians


In school, you learn early on that directions can be measured in and arc of degrees -- 360 degrees = one full rotation.

You also learn that the circumference of a circle is 2 * PI * radius, or 2Ï€r. That means if you take the radius (half distance across a circle) and lay it across the top of the circle, the radius would be used approximately 3.14 times for a half-circle. or 6.28 times for a full circle.

Using the radius as a unit of measurement is also called a "radian." So, there are 2*PI radians around a circle.

9/10/2016

Javascript: Using Namespaces

I'm not really too familiar with the concept of "namespaces," but essentially the gist seems to be that you want to avoid conflicts with existing structures that share the same name as your structures.

This might happen, for example, if you import a "library" of javascript functions.

You might have created a function called "displayCharacter()" or used a variable name like "hitpoints" without knowing that a javascript game library that you imported also has the same function name or variable name. In another case, maybe you are not so creative in your function names and you are prone to repeat usage of them -- ex. displayResult().

So, a way to avoid this might be to create your own unique "namespace" -- a sort of envelope that will hold some or all of the pieces of your specific program inside. The envelope is actually a new javascript object that you create, and then you sort of insert the objects into that enveloping namespace object using dot notation.

To set up a namespace, you would write a simple line of code like this:

var MyGame = MyGame || {};

What this statement does is it checks to see if the object "MyGame" already exists, and if it does not, then it creates a new blank object "{}". The resulting object is assigned to the variable name "MyGame," which, if it already exists is redundant, but if it does not exist creates your new empty namespace.

Now, that you have your namespace "MyGame", you can start inserting the parts of your program into the namespace using dot notation.

MyGame.name = "Dragon Magic";
MyGame.board = Object;
MyGame.score = 0;
MyGame.board.width = 200;
MyGame.board.height = 100;
MyGame.board.draw = function () {
  // code that draws the board on the screen
}

And, of course, you can also then refer to the variables and functions using the same namespace and dot notation.

alert("Welcome to " + MyGame.name + "!");
MyGame.board.draw();

8/16/2016

Advertising: Google Adsense/DFP -- How to Identify and Block an Obnoxious Ad or Videos from Appearing On Your Site

What is Google's Problem?


Google's AdSense network is still #1 in the world in 2016, though revenue is a fraction of what it used to be.

Much of the problems facing AdSense (and all Advertising networks) are Ad Blockers -- browser plug-ins or other software that stops ads from being served on publisher's websites. On my company's site, about 7% of people are using Ad Blockers, according to PageFair, a service that will attempt to monitor the use of Ad Blockers for you.

Why do so many people use AdBlockers? Because too many of the ads being served are Flash-based or otherwise sending out slow video ads or ads that open pop-ups or ads that redirect or spy on visitors in unwanted ways.

Obnoxious Ad Blocking On Your Site


One thing you do to help your visitors is to identify these terrible ad schemes. It can be difficult sometimes to do so, but Google does provide one good tool for identifying bad ads.

Get the plug-in.


Open a Chrome browser.

Visit the Google Publisher Toolbar page to install the plug-in.
  https://chrome.google.com/webstore/detail/google-publisher-toolbar/omioeahgfecgfpfldejlnideemfidnkc

After a minute it will install, and then you need to activate it in the upper right corner of the Chrome Browser.

It will require you to activate two of the components -- Google Adsense and DoubleClick for Publishers.

Find the Bad Ad


Next, go to your site, and reload until you get one of the ads. It's tedious, but if the bad ads are showing up repeatedly, then you should see one eventually. One ad on our site claims to be for a YouTube martial arts page, however, after a few seconds, the ad loads videos and plays them with sound. It's very jarring.

Once you see the ad, an overlay will appear. It may show the ad slot size, and maybe the URL of the link, and also the name of the Ad Network that bought the ad.

Block the Ad URL and Publisher in AdSense

Now, go to your AdSense account.


Once, there click on [Allow & Block ads].

There's two tabs you want to investigate here -- [Advertiser URLs] and [Ad networks]. 

Under [Advertiser URLs], copy and paste, or type in, the link's URL into the input field and hit save.

Under [Ad networks] search for the name of the offending Network. Once you find it, click on the slider to not allow it to show up again.

Then, just hope it works, and be patient -- it may take a few minutes to go into effect.

8/12/2016

Math: Geometry -- What is the forumula for the Area of a Triangle?

The formula for figuring out the area of a triangle, using only the base and height is:

    Area = 1/2 * (base * height)

Why? Because, you can duplicate the triangle, rotate it 180 degrees, and that will create a parallelogram. The area of a parallelogram is the same as an area of a rectangle => base * height.
So, if 2 of the same triangles = the same as one rectangle of equal base & height, then 1 triangle is half the size calculation of that rectangle.

8/04/2016

Javascript: String Replace More Than Once / All Instances of A Value

Javascript has a built-in function to replace a value found in a String with another value.
string.replace("match","replacement");

The problem is that it only does this replacement one time.

To replace all instances of a value in the string, you can combine two other functions -- split and join.

var myResult = myString.split("match").join("replacement");