Last Good Quote: Son's are the seasoning on our lives. - Someone on Facebook

Monday, January 31

Technical Debt

"Myrtle the Turtle told me it would take him 3 months to make my app, but Speedy Slim told me he could do it in 3 weeks? WTF?" my friend complains to me. I wince. This is not going to be easy to explain.

As with most things in life, both Speedy and Turtle are right but for different reasons. At the root of it is the Technical Debt that my friend is about to signup for.

Technical Debt is the "cost" of scaling, debugging and enhancing your application over its lifetime. Minimizing these cost up-front takes time. Sometimes a lot of time. Myrtle the Turtle is all about minimizing these costs.

An analogy that most laymen will understand

Over the entire life of your application there is a cost and the very first item that effects that cost is Speedy and Turtle. You can get this application built on cash, and pay upfront, and pay less. Or you can gt this application on credit and pay less up-front. The choice is really yours to make.

With a cash buy, you are paying every thing upfront. It's going to "hurt" more but once you get over that first build its relatively down hill from there, you will find that scaling, bugs and enhancements have a minimal cost.

With credit, your paying a little up-front but it hurts less...initially. As time passes on you'll be making continue payments to the debt of this purchase. You'll find that scaling, bugs and enhancements will cost you a fair amount of money. Inevidably, you'll pay more this way then you would from a build by Turtle. This is because of the interest on your technical debt.

What's the cost of using Speedy and receiving a "quicker" delivery?

  • Speedy is going to deliver exactly what you specify
  • Enhancements are going to take longer because Speedy will have to "re-work" a lot of code.
  • When more users start to use the app or more data gets into the system, the app will start to slow down and eventually will die
  • Speedy's going to get tired of working on the bad code in the app.
  • When you ask a "new" programmer to pickup the code up, you'll find that they tend to have to re-write the entire thing from scratch.
All of these are reasons that are not apparent in the initiall 3 to 6 months of the applications lifetime. They only become apparent down the road.

I want to point out:
  1. Even the most well built and thoughout applicaiton build can fall to the points above.
  2. There are developers out there who take 6 months but still deliver the equivalent of Speedy's work.
  3. It's not an easy thing to build a scalable, bug free, flexible application.
  4. Scaling, Bugs and Enhancements are NEVER free in any app. It's about minimizing the cost on these items.

When do I personally take Speedy up on his offer?

I'll take Speedy over Turtle when I know that what I want is a proto-type or proof of concept. I'll take Speedy when I "have" to have something done by a given date, and there is hard dollars tied to that date. I'll take Speedy when I don't know exactly what I want built yet, but I have a vague idea.

Everytime I take Speedy, I'll write down Turtle's name because I'm going to need him to build the real deal when the short need is done.

Are you a Speedy Slim or a Turtle Tim? Can a developer be both "on demand"? Which developer bills higher?

Thursday, January 27

More about Jarvis the Chat Bot

I mentioned that I created a chat bot named Jarvis. Since then I've been asked a few times what goes into creating Jarvis. I thought I'd take the time and explain what is going on behind the scenes.

First off Jarvis sits on top of database with the following tables.

  • word - A library of known words he found online
  • keywords - collections of words that Jarvis thought went together
  • responses - Response that can be given to a user
There are other tables, but that is the core ones.

Now I loaded Jarvis with the library that ELIZA the original chat bot used. That system had a number of keywords and responses to those key words. For example: If the user had typed "Hi", there were 3 possible responses. "How are you?", "Hello", "Welcome".

Jarvis would randomly pick one of those.

I also hand entered in some other "choice" keywords and phrases.

The next step was to have him learn from input. So when ever Jarvis puts out a response that includes a question (question mark), he would wait for the response and tag it as a possible "answer" to that question. That way when another user asked the question of Jarvis this was in his possible responses.

So for example, Jarvis might start off with a memory like the following:

Key: How are you?
Possible Responses: "Good", "I'm sad" or "I'm happy".

Let's say he had the following conversation with user 1.

Jarvis: Hi
User 1: Hello Jarvis
Jarvis: How are you?
User 1: I'm good, I had bacon this morning.


Now Jarvis' memory looks like the following:

Key: How are you?
Possible Responses: "Good", "I'm sad" or "I'm happy" or "I'm good, I had bacon this morning"


So when user 3 comes along the conversation looks like this...

Jarvis: Hello
User 3: Hi Jarvis, How are you?
Jarvis: I'm good, I had bacon this morning
User 3: That sounds good
Jarvis: how are you?
User 3: Hungry


Jarvis used the first users answers and he also learned a new answer to the question "How are you?"

Key: How are you?
Possible Responses: "Good", "I'm sad" or "I'm happy" or "I'm good, I had bacon this morning", "Hungry"


Curiosity
At first I built him so that any response that was a question was given priority. But that lead to Jarvis asking to many questions. So Jarvis now has a curiosity factor. The more curious he is, the more likey that he will give a response that is in the form of a question. This sponsors more responses for him.

You can increase or decrease curiosity by typing "moreCurious" or "lessCurious" into the text box.

Peeking into Jarvis Brain
There is a checkbox "Peek into Brain". Clicking this will let you see into Jarvis process. It shows you the following:

  • Words gathered from your input
  • Last 5 words learned (popularity is in parens)
  • The Keywords or phrases that were triggered based on your words
  • Selected/Best Keyword is highlights in bold
  • The Responses triggered from the best keyword
  • The last 5 learned keyword phrases
  • The last 5 learned responses
Scoreing
Jarvis tracks each chat session and gives it a score. Keep in mind each possible response is scored. Anytime Jarvis uses an response with a score higher than 0, he adds one to the session score.

This should lead to interesting sessions having a higher score, but I have not thoroughly tested that.

Jarvis can be found at http://www.mobeamer.com/lab/jarvis

Randomness

There are two places where Jarvis uses randomness.

First: Sometimes after finding all the keyphrases from the users input. Multiple keypharases have the same score. In this case, Jarvis will randomly select one of them.

Second: Sometimes after finding all responses from a keyphrase, mulitple responses have the same score. In this case, Jarvis will randomly select one.

The random function uses php's in-built rand() function. Which is not 100% random but close enough for me.

Monday, January 24

Jarvis - A chatterbot

If you didn't know AI (artificial intelligence) has become a bit of a hobby of mine. In an effort to explore the domain, I thought that I would throw together a little chat bot.

He's based off of the original chat bot, ELIZA.

I have/had a lot of thoughts of the direction I could take this in, but I wanted to get a version 1.0 all wrapped up and released before taking on other challenges.

You can chat with Jarvis at: www.mobeamer.com/lab/jarvis/

Some fun facts:
  • Jarvis was named after the AI in Iron Man
  • My 11 year old son, taught Jarvis a few key sayings
  • Sometimes Jarvis is incredibly stupid
  • Jarvis has a fully built out relationship model for words, key phrases and responses.
  • Jarvis can learn from chatting with other users
Some thoughts on what to implement next:
  • Allow Jarvis to "read" or learn from websites (Wikipedia)
  • Allow Jarvis to formulate higher "concepts" where responses are all connected via a single word or key phrase.
  • Allows users to chat with other users and Jarvis at the same time and ask them to spot Jarvis in the crowd
  • Allow Jarvis to get happier the longer someone chats with him
  • Add some type of visual representation of Jarvis

Friday, January 21

Charlotte BDPA - 2011 Kickoff

We had the Charlotte BDPA 2011 kickoff meeting last night. I think it went very well. A little recap of what I remember off the top of my head.:

  • Diondre, with IBN Consulting, is interested in teaching folks a number of IT topics, his business has an office downtown and has been training folks for a few months now. Definitely want to keep in touch with this guy.

  • Sheila (spl?) - The Urban League has a new program, they are giving CISCO certifications to 11th and 12th graders. The programs are held at Phillip O'Berry. Sounds like there are some nice perks with the program as well. (Laptop, software and such). She needs IT professionals to come by and speak about the career. I told her to count me in. If you know of anyone or are interested, reach out to me.

  • 2 BDPA members recently moved to new roles within thier current companies. You know I love to hear news like this.

  • The Charlotte BDPA 2011 calendar is full of education and training opportunities for adult professionals. A bit of a change in focus for our chapter but a refreshing one.

  • Charles - With APEX has a few development, PM and BA job opportunities for anyone who is looking.

All in all, it was a good meeting and better networking. I'm looking forward to our next meeting in Feb.

Hope you are starting the year off right.

Wednesday, July 14

5 Ways to be Lucky and Successful

Quite often I find myself talking about these rules during our weekly programming training classes (BDPA - HSCC).

Luck and success is all around you. But you have to be open to it. There is a mindset to being lucky and being successful. The following are some rules that help me to be lucky and successful:

Rule 1. Roll with the Changes
Change is going to come. We all make plans and life promptly crushes them. But when everything is falling apart, take the time to look around. Somewhere in the madness is an opportunity.

Grab it, catch it, put it in your back pocket, clean up your life, get back on track, then pull the opportunity out of your pocket and explore it.

Rule 2. Walk with open eyes
The simple act of noticing will bring luck to you. We don't always have to rush. Take the time to stroll and look around. You never know...
See that lady with the screaming four year old? She might have the job you've been looking for. Maybe you should have stopped and helped her.

Did you see that billboard about the master's degree? They might have a grant with your name on it.

See that flyer on the wall, don't you recognize that face? It's an old co-worker looking for a partner to start their next business.


3. Be Bold

Take risk, you don't have as much to lose as you think. Really has rejection ever killed anyone. Put yourself out there, so someone can pick you up. Keep in mind that if you let yourself, you will talk yourself out of everything that was meant for you.

4. Know when to quit
Because you are now taking risks and being bold, you will find a lot of things going on in your life. This is good, you're enjoying life. But at some point it will be too much. I know when I reach this point because I start to habitually avoid doing things. So, the time has come to trim to fat and let something go. Choose carefully, but admit and realize that something has to go.

On the other hand, be honest about your efforts are they profitable, monetarily or emotionally. If you ain't getting no satisfaction its a good sign that it's time to cut it loose. Life is to short to spend it on the un-enjoyable.

5. Make "me" time
Leave time to do nothing. I repeat nothing. Pretend that you're going to sit on your butt and do...wait for it...nothing. You'll find that this is the most enjoyable time you have. You will look forward to this time. You will crave it. The day just won't seem right without it. Why?

Because your nothing time turns into the time you do the thing you absolutely 100% enjoy doing above anything else. You have no obligations, you can do anything you want. You will naturally do what you like the most. Surprisingly you will find that this activity will change week to week. Your brain's appetite is large, once you allow it to join the buffet.

Now, don't go crazy, you can't have "me" time all of the time. Then the pleasure of it goes away, not to mention that the rest of your life will go sideways on you.

So there you have it. 5 simple rules that I live by. They help me be lucky and successful,. They can definitely help you.

What rules would you add?

Monday, July 12

Intro to Data Warehouses

This is a recent presentation I gave on data marts and data warehousing techniques. This only scratches the surface and there are a loot of places to dive deeper.


Date Warehousing

Monday, May 17

5 min Intro to PHP

If your interested in learning or playing with PHP. Here is a short introduction to get you started. I expect that you have some basic programming skills already. (or the will power to stay and play for a while)

Download It

If your using a window OS you will want an "XAMP" installation. It installs Apache, PHP and MySQL on windows. Most of them are simple: download, unzip and click the "start" executable. I like to use Uniform Server. I won't go into debugging apache in this article, but I will suggest that you shut off any program that uses the web server ports. (Visual Studio, IIS, Skype).

Alternatively you can play on any website you have, most will have php enabled.

Basic Things to know

  • Save your page with a .php extension
  • Surround your code with <?php ...code.... ?>
  • You can use <? ...code.... ?> but that is non-standards compliant
  • All statements in php must end with ";"
  • Variables start with $. IE: $username, $today, $yesterday, $i
  • Variables "live" to the end of page, but do not carry over into functions
  • Single line comments use //
  • Multi line comments use /* .... */
  • To add strings use "." (IE: $firstName . " " . $lastName)
  • To add numbers use "+" (IE: $age + 10)
  • Use print to print (IE: print "Hello " . $username)
  • Use echo to print (IE: echo "Hello " . $username)
If statements

if( boolean )
{
//...some code
}
elseif( boolean )
{
//...some code
}
else
{
//...other code
}

Loops

for($i=0;$i<10;$i++)
{
//...code
}

while( boolean )
{
// ...code
}

Variables, Sessions and Forms

Normal Variable: $username;
Session Variable: $_SESSION["username"]
Form Post Variable: $_POST["username"]
Form Get Variable: $_GET["username"]

Kill a session variable: $_SESSION["username"] = "";


Database

PHP normally uses mySQL, but each of the functions below have an equivalent function for most database systems.

$db_host = "localhost";
$db_user = "user";
$database = "dbname";
$db_passwd = "pass";
mysql_connect($db_host, $db_user, $db_passwd);
$q = mysql_query("select * from user");

while($row = mysql_fetch_object($q))
{
print $row->username;
}


Alternativly you can use mysql_fetch_row($q)...this will get an array of the field values and you can access them by $row[0], $row[1]....etc.

As with most high level languages, php has a number of functions available to it. You can search the very friendly documentation at www.php.net


Objects and Classes
Class DateUtils
{

function DateUtils()
{
//...constructor
}


function getToday($format)
{
return date($format);
}
}

And here is how to use the class

$util = new DateUtils();
print $utils->getToday();



What else would you like to know?

Monday, April 26

CSS: Tabbed Menu

Free Code. This comes directly from this site http://www.webcredible.co.uk/user-friendly-resources/css/css-round-corners.shtml



Creates rounded menus.

You will need the following four images:
  • - Right Tab
  • Left Tab

  • Right Tab Hover

  • Left Tab Hover



  • Code

    <html>

    <style>
    #navigation a
    {
    color: #000;
    background: #ffa20c url(left-tab.gif) left top no-repeat;
    text-decoration: none;
    padding-left: 10px
    }

    #navigation a span
    {
    background: url(right-tab.gif) right top no-repeat;
    padding-right: 10px
    }

    #navigation a, #navigation a span
    {
    display: block;
    float: left
    }

    /* Hide from IE5-Mac \*/
    #navigation a, #navigation a span
    {
    float: none
    }
    /* End hide */

    #navigation a:hover
    {
    color: #fff;
    background: #781351 url(left-tab-hover.gif) left top no-repeat;
    padding-left: 10px
    }

    #navigation a:hover span
    {
    background: url(right-tab-hover.gif) right top no-repeat;
    padding-right: 10px
    }

    #navigation ul
    {
    list-style: none;
    padding: 0;
    margin: 0
    }

    #navigation li
    {
    list-style: none;
    float: left;
    margin: 0;
    }
    </style>



    <body>
    <h1>Tabbed Menu Test</h1>

    <ul id="navigation">
    <li><a href="#"><span>Home</span></a></li>
    <li><a href="#"><span>Services</span></a></li>
    <li><a href="#"><span>Take a tour</span></a></li>
    <li><a href="#"><span>About us</span></a></li>
    <li><a href="#"><span>Contact us</span></a></li>
    </ul>

    </body>
    </html>

    Friday, April 23

    Javascript - 2D Map Library

    This article is a wrap up of a series of articles in which I walk through building a simple 2d top down map library. Below are the articles that build this library:
    For those of you that want the code, scroll past the explanations, it's at the bottom.

    Style.css.
    While testing and playing I usually will include the style in one page, for the ease of editing, but it's always a good idea to separate the style sheet from the main body of code. This allows an artist to come along and play with the look and feel of the site without screwing with your brilliantly created code.

    Map.js.
    All the general re-usable functions for mapping. If you ever finish coding a function and think, man I'll never have to touch this again, its so perfect and I'll use it all the time! First, slap yourself, cause we all know it's going to have a bug in it at some time. Second realize that the function in question, is prime material to go into a library of sorts. The functions in map.js are generic and can be kept from game to game as you build different things. At least that is my hope.

    TileClicked()
    I left tile clicked in the main body of the page because the actions you might want to take when a tile is clicked will change from game to game. Thus it is not library material.

    DestReached()
    This is a new function that was not discussed in other articles. Once a unit is done moving to it's destination of location, this function is called. I figured game builders might want to change this function depending on the game.

    Play()
    This is the heart of your game, if you want enemies to run around randomly, here is where you put that stuff. This function will call itself every few milliseconds, the more code in this function the slower your game is going to run.

    ObjectsCollided()
    This function is called when ever two units combine. The unit that moved last and did the collision is passed along with the id of each unit that is involved in the collision. You'll want to customize this function.


    The Body Tag
    The body tag calls the buildMap and addUnit function. I'd expect that you will want to change that.

    Div Elements
    There are two divs in the html one to hold the map and another to hold the score. You can move those around, but they must be somewhere in the page for the library to work.

    Map.js Function List

    BuildMap(width, height)
    Builds a map of width and height. It will also add walls to all edges of the map, so units don't wonder off it. Comment out the "addBorders()" line if you don't want this.

    AddBorders()
    Ummm, it adds borders...nuff said

    addWall(x,y)
    Turns tile x,y into a wall. Sets tile's flag = -1, sets the background color

    addUnit(unitID, x, y)
    Adds a unit with that ID to the map at tile location x, y. Multiple units can be added. If unitID is 1000 it is given the css class "unit". Otherwise the class is "enemy"

    setWalkableFlag(x, y, flag)
    Sets tile x, y "flag" variable to the flag passed.

    jumpUnit(unitID, tileDestX, tileDestY)
    Moves a unit directly to that tile, no animation at all...unit just jumps to location.

    move(unitID, dir)
    Move a unit one tile in the direction specified. Valid directions are N, E, S, W. This is an animated move (one pixel at a time). This uses the moveUnit() function.

    moveUnit(unitID, tileDestX, tileDestY)
    Moves a unit to the tile passed in. If at anytime the unit hits a none walkable tile, the unit will move back to last position. (no route finding). Calls DestReached() when completed.

    isWalkable(x,y)
    Returns "Y" or "N" if pixel x, y is walkable

    isWalkableTile(x,y)
    Returns "Y" or "N" if tile x, y is walkable

    getTop(obj)
    Return the top pixel (y) of the object. Could use some optimization

    getLeft(obj)
    Return the left pixel (x) of the object. Could use some optimization

    translateTileX(x), translateTileY(y)
    return the tileX that pixel x is located within

    getTileX(unitID), getTileY(unitID)
    return the tile x and tile y that the unit is located on

    Here be code!

    Style Sheet (style.css)


    .tile {
    background:#BBB;
    border:1px solid #999;
    position:absolute;
    top:0px;left:0px;
    width:5px;height:5px;
    overflow:hidden
    }

    .unit {
    background:green;
    border:1px solid #999;
    position:absolute;
    top:0px;left:0px;
    width:5px;height:5px;
    overflow:hidden
    }

    .enemy {
    background:red;
    border:1px solid #999;
    position:absolute;
    top:0px;left:0px;
    width:5px;height:5px;
    overflow:hidden
    }

    .food {
    background:black;
    border:1px solid #999;
    position:absolute;
    top:0px;left:0px;
    width:5px;height:5px;
    overflow:hidden
    }



    Map.js (the library)



    var originX = 0;
    var originY = 0;
    var tileSize = 16;
    var mapHeight = 0;
    var mapWidth =0;
    var score=0;
    var playSpeed = 1000;
    var numUnits = 0;
    var maxNumUnits = 40;


    function buildMap(width, height)
    {
    mapHeight = height;
    mapWidth = width;

    for(x=0;x<width;x++)
    for(y=0;y<height;y++)
    {
    var d = document.createElement("DIV");
    d.className="tile";
    d.setAttribute("ID","tile_" + x + "_" + y);
    d.style.top = originY + (y*tileSize);
    d.style.left = originX + (x*tileSize);
    d.style.width = tileSize;
    d.style.height = tileSize;
    d.setAttribute("flag","0");
    d.setAttribute("onclick","tileClicked(" + x + "," + y + ")")
    document.getElementById("divMap").appendChild(d);
    }

    addBorders();



    }

    function addBorders()
    {
    for(x=0;x<mapWidth;x++)
    {
    addWall(x, 0);
    addWall(x, mapHeight-1);
    }


    for(y=0;y<mapHeight;y++)
    {
    addWall(0, y);
    addWall(mapWidth-1,y);
    }
    }

    function addWall(x,y)
    {
    var tile = document.getElementById("tile_" + x + "_" + y)
    tile.setAttribute("flag","-1");
    tile.style.background = "#777"
    }


    function addUnit(unitID, x,y)
    {
    var d = document.createElement("DIV");
    var tile = document.getElementById("tile_" + x + "_" + y)
    if(unitID == 1000)
    {
    d.className="unit";
    }
    else
    {
    d.className="enemy";
    }
    d.setAttribute("xVel", 0);
    d.setAttribute("yVel", 0);
    d.setAttribute("ID","unit_" + unitID);
    d.style.top = tile.style.top;
    d.style.left = tile.style.left;
    d.style.width = tileSize;
    d.style.height = tileSize;
    d.setAttribute("currTileX",x);
    d.setAttribute("currTileY",y);
    d.setAttribute("priorTileX",x);
    d.setAttribute("priorTileY",y);

    setWalkableFlag(x, y, unitID);

    document.getElementById("divMap").appendChild(d);
    }

    function setWalkableFlag(x, y, flag)
    {
    var tmpTile = document.getElementById("tile_" + x + "_" + y)
    tmpTile.setAttribute("flag", flag);

    }

    function jumpUnit(unitID, tileDestX, tileDestY)
    {
    var unit = document.getElementById("unit_" + unitID);
    var tile = document.getElementById("tile_" + tileDestX + "_" + tileDestY)
    if(!tile)
    {
    return;
    }
    unit.style.left = getLeft(tile);
    unit.style.top = getTop(tile);
    //
    //mark the current tile as UNwalkable
    //
    setWalkableFlag(unit.getAttribute("currTileX"), unit.getAttribute("currTileY"), "0");

    //
    //mark the old tile as WALKABLE
    //
    setWalkableFlag(unit.getAttribute("priorTileX"), unit.getAttribute("priorTileY"), "0");

    unit.setAttribute("currTileX",x);
    unit.setAttribute("currTileY",y);
    unit.setAttribute("priorTileX",x);
    unit.setAttribute("priorTileY",y);

    }



    function move(unitID, dir)
    {
    x = getTileX(unitID)
    y = getTileY(unitID)

    if(dir == "N")
    {
    y--;
    }

    if(dir == "E")
    {
    x++;
    }

    if(dir == "S")
    {
    y++;
    }

    if(dir == "W")
    {
    x--;
    }


    if(isWalkableTile(x, y) == "Y")
    {
    moveUnit(unitID, x, y);
    }


    }


    function moveUnit(unitID, tileDestX, tileDestY)
    {

    var unit = document.getElementById("unit_" + unitID);
    var tile = document.getElementById("tile_" + tileDestX + "_" + tileDestY)
    unit.setAttribute("priorTileX",getTileX(unitID));
    unit.setAttribute("priorTileY",getTileY(unitID));

    if(!tile)
    {
    alert("no tile found");
    return;
    }
    x = getLeft(unit);
    y = getTop(unit);
    destX = getLeft(tile);
    destY = getTop(tile);
    newX = x;
    newY = y;

    if(x > destX) newX--;
    if(x < destX) newX++;
    if(y > destY) newY--;
    if(y < destY) newY++;

    if(isWalkable(newX, newY) == "Y" && isWalkable(newX+tileSize-2, newY + tileSize-2) == "Y")
    {
    unit.style.left = newX;
    unit.style.top = newY;

    if(newX != destX || newY != destY)
    {
    setTimeout("moveUnit(" + unitID + "," + tileDestX +"," + tileDestY+")",5);
    }
    else
    {
    destReached(unitID, destX, destY);
    }
    }

    }

    function isWalkable(x,y)
    {
    var tile = document.getElementById("tile_" + translateTileX(x) + "_" + translateTileY(y))
    if(tile.getAttribute("flag") >= 0) return "Y";


    return "N";
    }


    function isWalkableTile(x,y)
    {
    var tile = document.getElementById("tile_" + x + "_" + y)
    if(tile.getAttribute("flag") >= 0) return "Y";


    return "N";
    }

    function getTop(obj)
    {
    if(obj)
    {
    return parseInt(obj.style.top.replace("px",""));
    }

    return 0;
    }

    function getLeft(obj)
    {
    if(obj)
    {
    return parseInt(obj.style.left.replace("px",""));
    }

    return 0;
    }


    function translateTileX(x)
    {
    return Math.floor(x/tileSize - originX);
    }

    function translateTileY(y)
    {
    return Math.floor(y/tileSize - originY);
    }


    function getTileY(unitID)
    {
    var unit = document.getElementById("unit_" + unitID);
    return translateTileY(getTop(unit));
    }

    function getTileX(unitID)
    {
    var unit = document.getElementById("unit_" + unitID);
    return translateTileY(getLeft(unit));
    }

    function getTileY(unitID)
    {
    var unit = document.getElementById("unit_" + unitID);
    x = Math.floor(getLeft(unit)/tileSize - originX);
    y = Math.floor(getTop(unit)/tileSize - originY);

    return y;
    }




    Basic HTML page (index.html)


    <html>
    <link type="text/css" href="style.css"rel="stylesheet" />
    <script language=javascript src="map.js"></script>

    <script language=javascript>
    function tileClicked(x,y)
    {
    //called whenever a tile is clicked
    moveUnit(1000, x, y);
    }

    function destReached(unitID, x, y)
    {
    //called when ever the unit is done moving to a spot

    }


    function play()
    {
    //once called, this will loop forever, checking the game state and other things
    setTimeout("play()",playSpeed);
    }


    function objectsCollided(unit, unitID, enemyID)
    {
    //called whenever two objects collide

    }

    </script>

    <body onload="buildMap(10,10); addUnit(1000,4,4);">

    <div id="divMap"></div>

    <div id="score" style="font-family:verdana;size:14px; background:green;position:absolute;top:5px;left:350px; width:100px height:15px;border:5px solid green;">
    Score: 0
    </div>


    </body>
    </html>

    Thursday, April 22

    Stock Guessing - Programatically

    I've always been interested in stock analytics. Mostly because I have this un-reasonable dream that if I can program a stock "machine" which will trade stocks for me and make me richer than my wildest dreams.

    *Watches as you fall on the floor laughing*

    So now that you are done laughing....I started a blog about a year ago on creating such a program. If your interested it's here. I don't think I'm going to post to it anymore and it..."wonders"...a bit.

    Last night, I fired up the old program I wrote and tinkered with it for a little while. Tormenting myself with that dream I mentioned. To my surprise, I found something interesting...

    The program is setup to run once a day, pick a few stocks and then invest $1,000 into it. It then examines it's buys every day and sells the stock. There is a lot of other stuff going on, but that's the important part.

    If I had $10,000 to invest over the past 60 days and I had done ever trade and sell recommended by the program. I'd have gained $3,679.02.

    I'd have done 33 trades, assuming a $10 commission on each buy and sell, the commissions would cost me $660.

    The program churns through around 3,500 stocks (NYSE and NASDAQ) looking for good trades. It's a lucky day when it finds two picks in a given day.

    For those who are interesting..here are the last 10 or so picks it spit out.




    I'm at a loss on how to further test the program to ensure this is not some coincidence. Any suggestions?

    Followers