Saturday, July 31, 2010

removing duplicates from an array

I searched online to look for a decent algorithm to remove duplicate values from array but didn't get any thing that was successful. There were couple but none of them worked if you had multiple no of duplicates.

The following algorithm works despite the no of duplicates in an array. This method works for me as I needed a sorted array...


_array.sort(); // shorts the array so that all the similar values are together

var firstWord:String; // variable for the first word
var secondWord:String; //variable for the second word
for(var j:int =0; j<= _array.length-1; j++)
{
firstWord = _array[j];
secondWord = _array[j+1]; //trace("f: " + firstWord + " S: " + secondWord);

if(firstWord == secondWord) //if the first word and second word is similar
{
_array.splice(j+1,1); // remove the second word from array
j--; // decrease value of counter to recheck for same word
}
}

Thursday, July 15, 2010

Android on iPhone

I upgraded my iPhone to os 4.0 from os 3.1. It seemed pretty cool with multitask(kind of) functionality but later I realized that there is no reception. No, I am not talking about new iPhone 4.0 and its hardware issue. The one I have is iPhone 3G.

After few research I found out that iPhone 3G, jail broken with redSnow has the reception. The phone was pretty much useless as I wasn't able to make any phone calls from it. Then I did a little bit more research and found out that I can install Android on iPhone. So I decide to give it a try I had nothing to lose...

The software needed to install android on iPhone is called iphodroid. After few hours of trial and error I was finally able to install a stable version of Android on iPhone. When I installed it for the first time it wasn't responding to the touch. I uninstalled and reinstalled the Android it fixed the issue. The phone was all set to go.

Since it was the fist installation there wasn't even a single contact in my address book. I loged in to google and synced my contact. Since, my google account was synced with itunes all of my contacts was on my new phone.

It was kind of wired to use the phone for the first time because the buttons responded differently than iPhone but it didn't take long for me to figure out the functionality of the buttons. One the first thing that I noticed is that the touch response is kind of slow specially after using iPhone. The user interface isn't that intuitive specially due to the slow response to touch.

One of the main reason I tried Android on iPhone was because the ability to play Flac files via andless app. But it was no use because there was no way for me to upload the music files to the device. The andless app looks for SD to play the music which obesely is not iPhone. So it was no use at all.

Another thing I noticed that the device was running kind of hot and it was sucking all the juice. After continually using the phone for 1.5 hrs the battery was almost dead..

So, my recommandation is not to install Android on iPhone to replace iPhone os.. at least for now..

Monday, June 21, 2010

Notorious Tween and the Garbage Collector Issues

I love tween and use it a lot while making websites and applications. But whenever I use more than 3 tweens simultaneously it doesn't work properly. It works sometimes and sometimes it just freezes in the middle and any Event Listener that has been called is not triggered. Moreover it works on some computer and in some it doesn't.

Before I tell you how to fix it let me explain why it happens. Flash player runs GC (Garbage Collector) once it executes the script. It does this to free up the memory and enhance the performance. Now they way flash player runs the GC depends on the system resource. So if the users computer has less memory GC is triggered earlier and if the user runs the program on the same computer when more memory is available it triggers the GC little late.

Most of the time tween gets stuck if you have code like below where the tween time is different.

var a:Tween = new Tween(a_mc, "y", Back.easeIn, -75, 0, 1, true);
var bTween = new Tween(b_mc, "y", Back.easeIn, -75, 0, 2, true);
var c:Tween = new Tween(c_mc, "y", Back.easeIn, -75, 0, 3, true);
c.addEventListener(TweenEvent.MOTION_FINISH, loadThis);

function loadThis(e:TweenEvent):void
{
trace ("It's Loaded");
}

here the Flash Engine runs all the scripts at same time and when the first tween is finished the GC disables all the tweens. A better way to code is to change the starting "y" axis.

var a = new Tween(a_mc, "y", Back.easeIn, -95, 0, 1, true);
var b = new Tween(b_mc, "y", Back.easeIn, -85, 0, 1, true);
var c = new Tween(c_mc, "y", Back.easeIn, -75, 0, 1, true);

function loadThis(e:TweenEvent):void
{
trace ("It's Loaded");
}


this way, the tween finishes at the same time, the movie clips reaches the destination in different time like the previous code and have less change to effected by GC. Now, this is not the foolproof. It still gets stuck once in a while. This is the issue with Flash Player and there is not way out, for at least now. The issue gets even worse when functions are triggered based on the Event Listener.

To make sure that the functions are running even when the tween gets stuck we can create timer function. In this function we can run a conditional statement to check if the tween has completed and the event has triggered. Here is the code for that

var activated:Boolean;
var myTimer:Timer = new Timer(1010,1);

var a = new Tween(a_mc, "y", Back.easeIn, -95, 0, 1, true);
var b = new Tween(b_mc, "y", Back.easeIn, -85, 0, 1, true);
var c = new Tween(c_mc, "y", Back.easeIn, -75, 0, 1, true);

function loadThis(e:TweenEvent):void
{
activated = true;
trace ("It's Loaded");
}

myTimer.start();
myTimer.addEventListener(TimerEvent.TIMER, checkTween);

function checkTween(e:TimerEvent):void
{
if(activated == false)
{
trace("It's Loaded");
}
if(a_mc.y <=-1 || b_mc.y <=-1 || c_mc.y <=-1)
{
a_mc.y = b_mc.y = c_mc.y = 0;
}
}

Thursday, June 17, 2010

Switch Case = Advance If else

If you haven't used Switch conditional statement then you are punishing yourself. By using switch statement you can reduce the code by 60% and is lot easier to read and understand.

Here is a little code for linking multiple websites to multiple button by calling a function. Now isn't that a awesome, one function handeling all MouseEvents


a_btn.addEventListener(MouseEvent.CLICK, openURL);
b_btn.addEventListener(MouseEvent.CLICK, openURL);
c_btn.addEventListener(MouseEvent.CLICK, openURL);

function openURL(e:MouseEvent):void
{
var url:String = new String(); // Creating a String Variable to pass URL
switch(e.target.parent.name) // Calling the instance name
{
// here it's checking if the name of the instance is "a_btn"
case "a_btn": // if the condition is true
url = "http://www.A.com/"; // do this
break; // and exit the loop
case "b_btn": // if the condition is true
url = "http://www.B.com"; //do this
break; // and exit the loop and so on.......
case "c_btn":
url = "http://www.C.com";
break;
default:
trace("None of the statement is true.")
}

// Once the conditional statement finishes
var myRequest:URLRequest = new URLRequest(url); // created a url request
navigateToURL(myRequest); // open the url request
}


One thing you have to be careful about he is the colon(:). The case statement ends with colon not with semicolon as other statements does.
And that is it. All the Mouse Click Event calling same function. The function check which Mouse Click Occurred base on that you call other functions of task.

Cups and Coin

Wow, it took a while for me to upload another tutorial. Sorry folks, I was working on Actionscript 3.0, XML, PHP and MySql site, NepaliRecipes.com. It is still on beta version but one can submit and search for Nepali Recipes. Now about this Game, Cups and Coin.

I programmed this game for my class project but it had few issues. First it had 459 lines of code and couple of external classes. I reduce the code to less than 200 line and no external classes. Beside that, there was some kind of bug that kept on changing the initial position of the cups after each animation. Finally, I figured it out. It was the version of Flash Player. If you use other older version then 10.1 it freezes once in a while. The 10.1 version of Flash Player and Flash CS5 handles the Tween Event with very less errors.

So, how does the game work? There are 3 cups and a coin. The coin is put inside one of the cup and moved randomly. A player has to figure out which cup has the coin. Pretty straight forward. After every correct answer level goes up, which increased the number of times the cups are moved and the moves gets faster, i.e. decreases the time. If the player gets 3 wrong picks, the game is over.
There are three life and unlimited level, I was able to play up to level ten.

The main logic I used in this game is the coin is always on the same cup, Cup A. The position of Cup A keeps on changing every time, if the player picks Cup A, he finds to coin. Since all the cups as identical, player has to visually keep track of the cup A.

Now, try the Game:


And now here is the source file and the following is the code.


import fl.transitions.Tween;
import fl.transitions.TweenEvent;
import fl.transitions.easing.*;
import flash.events.MouseEvent;

var reset_mc:mcReset = new mcReset();

var cupAx:Number = new Number(cupA_mc.x);
var cupAy:Number = new Number(cupA_mc.y);
var cupBx:Number = new Number(cupB_mc.x);
var cupBy:Number = new Number(cupB_mc.y);
var cupCx:Number = new Number(cupC_mc.x);
var cupCy:Number = new Number(cupC_mc.y);

var randomFirst:Number;
var randomSecond:Number;

var cupsArray:Array = new Array(cupA_mc, cupB_mc, cupC_mc);

var level:Number = new Number(0);
var counter:Number = new Number(0);
var time:Number = new Number(.6);
var life:Number = new Number(3);

play_mc.addEventListener(MouseEvent.CLICK, startGame);
play_mc.buttonMode = true;

level_txt.text = "0";
life_txt.text = life.toString();

function startGame(e:MouseEvent):void
{
// Disabling the play button
play_mc.alpha = 0;
play_mc.buttonMode = false;
play_mc.removeEventListener(MouseEvent.CLICK, startGame);
//Fading out the coin before the cup start moving
var myAlphaTween:Tween = new Tween(coin_mc, "alpha", Regular.easeOut, 1, 0, 1, true);
myAlphaTween.addEventListener(TweenEvent.MOTION_FINISH, selectRandomCup);
counter = 0;
level_txt.text = level.toString();
}



function selectRandomCup(e:TweenEvent):void
{
randomFirst = Math.ceil(Math.random()* 3); //generating the first random number
randomSecond = Math.ceil(Math.random()* 3); // generating the second random number
while(randomFirst == randomSecond) //run this loop untill the random second no is different than random first no
{
randomSecond = Math.ceil(Math.random()* 3);
}
if(randomFirst != randomSecond) // once the random numbers are different start swaping
{
//Getting cups from cupsArray using its index number
// Since the random no is between 1-3 and array length is 2, -1 is used so that there is no error.
startSpin(cupsArray[randomFirst-1], cupsArray[randomSecond-1]);
}
}


function startSpin(firstCup:MovieClip, secondCup:MovieClip):void
{
disableCupClicks();// disabling the cups to be clicked
setChildIndex(coin_mc,0); //Sending the coin to back of the cup(add remove child doesn't work,bug)

//Moving the first coin
var cupATweenX:Tween = new Tween(firstCup, "x", Regular.easeOut, firstCup.x, secondCup.x, time, true);
var cupATweenY:Tween = new Tween(firstCup, "y", Regular.easeOut, firstCup.y, secondCup.y, time, true);
//Moving the second coin
var cupBTweenX:Tween = new Tween(secondCup, "x", Regular.easeOut, secondCup.x, firstCup.x, time, true);
var cupBTweenY:Tween = new Tween(secondCup, "y", Regular.easeOut, secondCup.y, firstCup.y, time, true);
//increasing the counter once the move is completed
counter++;
//once the animation is doing call swap again
// Use the MOTION_STOP. For some reason MOTION_FINISH keeps on freezing randomly
cupBTweenY.addEventListener(TweenEvent.MOTION_STOP, swapAgain);
}

function swapAgain(e:TweenEvent):void
{
if(level >= counter) //Checking if the move needs to occur again
{
selectRandomCup(e);
}
else
{
enableCupClicks();
}
}

function enableCupClicks():void
{
cupA_mc.buttonMode = true;
cupB_mc.buttonMode = true;
cupC_mc.buttonMode = true;
cupA_mc.addEventListener(MouseEvent.CLICK, rightAnswer);
cupB_mc.addEventListener(MouseEvent.CLICK, wrongAnswer);
cupC_mc.addEventListener(MouseEvent.CLICK, wrongAnswer);
}


function disableCupClicks():void
{
cupA_mc.buttonMode = false;
cupB_mc.buttonMode = false;
cupC_mc.buttonMode = false;
cupA_mc.removeEventListener(MouseEvent.CLICK, rightAnswer);
cupB_mc.removeEventListener(MouseEvent.CLICK, wrongAnswer);
cupC_mc.removeEventListener(MouseEvent.CLICK, wrongAnswer);
}

function rightAnswer(e:MouseEvent):void
{
setChildIndex(coin_mc,5); //Bringing the coing to front
coin_mc.x = cupA_mc.x + cupA_mc.width/2 - coin_mc.width/2; // matching its position with cup A
coin_mc.y = cupA_mc.y+ cupA_mc.height/2 - coin_mc.height/2;
var myAlphaTween:Tween = new Tween(coin_mc, "alpha", Regular.easeOut, 0, 1, .5, true); // Animating it to be visible
checkTime(); //reducing the time if needed
level++; //increasing the level
startGame(e); //starting the game again
}

function wrongAnswer(e:MouseEvent):void
{
if(life >= 1)
{
life --; // Reducing the life count
life_txt.text = life.toString(); //Dispaying the text
setChildIndex(coin_mc,5); // Making the coin visible
coin_mc.x = cupA_mc.x + cupA_mc.width/2 - coin_mc.width/2; // Matching its posistion with cup A
coin_mc.y = cupA_mc.y+ cupA_mc.height/2 - coin_mc.height/2;
var myAlphaTween:Tween = new Tween(coin_mc, "alpha", Regular.easeOut, 0, 1, .5, true);
startGame(e);
}
else // if the life is 0
{
disableCupClicks();
addChild(reset_mc); // show Reset gamebutton
reset_mc.x = -1;
reset_mc.y =stage.stageHeight - reset_mc.height;
reset_mc.buttonMode = true;
reset_mc.addEventListener(MouseEvent.CLICK, reload);
}
}

function reload(e:MouseEvent):void
{
// Reseting everything
removeChild(reset_mc);
play_mc.alpha = 1;
play_mc.buttonMode = true;
play_mc.addEventListener(MouseEvent.CLICK, startGame);
level = 0;
level_txt.text = level.toString();
counter = 0;
time = .6;
life = 3;
life_txt.text = life.toString();
setChildIndex(coin_mc,5);
coin_mc.x = cupA_mc.x + cupA_mc.width/2 - coin_mc.width/2;
coin_mc.y = cupA_mc.y+ cupA_mc.height/2 - coin_mc.height/2;
}
function checkTime():void
{
// if the time is less than 0.2 sec it is very hard to see the animation
if(time >= .2)
{
time -= .07;
}
}

Sunday, September 13, 2009

How Aperture Works?

For now just how Aperture Works


var whiteCircle_mc:whiteCircle = new whiteCircle();
var leafA_mc:mcNewLeaf = new mcNewLeaf();
var leafB_mc:mcNewLeaf = new mcNewLeaf();
var leafC_mc:mcNewLeaf = new mcNewLeaf();
var leafD_mc:mcNewLeaf = new mcNewLeaf();
var leafE_mc:mcNewLeaf = new mcNewLeaf();

var leafAInit:Number = new Number(0);
var leafInitial:Number = new Number(0);
var leafRotation:Number = new Number(-72);
var leafA_mcX:Number = new Number(53);
var leafA_mcY:Number = new Number(175);

addChild(whiteCircle_mc);
whiteCircle_mc.x = 200;
whiteCircle_mc.y = 219;

addChild(leafA_mc);
leafA_mc.x = leafA_mcX;
leafA_mc.y = leafA_mcY;
leafA_mc.rotation = leafInitial;

addChild(leafB_mc);
leafB_mc.x = 112;
leafB_mc.y = 346;
leafB_mc.rotation = leafInitial + leafRotation;

addChild(leafC_mc);
leafC_mc.x = 292;
leafC_mc.y = 346;
leafC_mc.rotation = leafInitial + (leafRotation * 2) ;

addChild(leafD_mc);
leafD_mc.x = 347;
leafD_mc.y = 173;
leafD_mc.rotation = leafInitial + leafRotation * 3 ;

addChild(leafE_mc);
leafE_mc.x = 200;
leafE_mc.y = 65;
leafE_mc.rotation = leafInitial + leafRotation * 4 ;


////// Circle on The Top /////
var topCircle_mc:topCircle = new topCircle();
addChild(topCircle_mc);
topCircle_mc.x = 200;
topCircle_mc.y = 220;
topCircle_mc.alpha = 1;


///// Aperture Buttons /////
fOneFour.addEventListener(MouseEvent.MOUSE_OVER, oneFourF);
fTwo.addEventListener(MouseEvent.MOUSE_OVER, twoF);
fTwoEight.addEventListener(MouseEvent.MOUSE_OVER, twoEightF);
fFour.addEventListener(MouseEvent.MOUSE_OVER, fourF);
fFiveSix.addEventListener(MouseEvent.MOUSE_OVER, fiveSixF);
fEight.addEventListener(MouseEvent.MOUSE_OVER, eightF);
fEleven.addEventListener(MouseEvent.MOUSE_OVER,elevenF);
fSixteen.addEventListener(MouseEvent.MOUSE_OVER, sixteenF);
fTwentytwo.addEventListener(MouseEvent.MOUSE_OVER, twentytwoF);
show_mc.addEventListener(MouseEvent.CLICK, showCircle);
hide_mc.addEventListener(MouseEvent.CLICK, hideCircle)

show_mc.buttonMode = true;
hide_mc.buttonMode = true;

function oneFourF(event:MouseEvent):void
{
leafInitial = 0;
rotateLeaf();
}

function twoF(event:MouseEvent):void
{
leafInitial = -3.8;
rotateLeaf();
}

function twoEightF(event:MouseEvent):void
{
leafInitial = -7.6;
rotateLeaf();
}

function fourF(event:MouseEvent):void
{
leafInitial = -11.4;
rotateLeaf();
}


function fiveSixF(event:MouseEvent):void
{
leafInitial = -15.2;
rotateLeaf();
}

function eightF(event:MouseEvent):void
{
leafInitial = -19;
rotateLeaf();
}

function elevenF(event:MouseEvent):void
{
leafInitial = -22.8;
rotateLeaf();
}

function sixteenF(event:MouseEvent):void
{
leafInitial = -26.6;
rotateLeaf();
}


function twentytwoF(event:MouseEvent):void
{
leafInitial = -30.4;
rotateLeaf();
}


function rotateLeaf():void
{
leafA_mc.rotation = leafInitial;;
leafB_mc.rotation = leafInitial + leafRotation * 1;
leafC_mc.rotation = leafInitial + leafRotation * 2;
leafD_mc.rotation = leafInitial + leafRotation * 3;
leafE_mc.rotation = leafInitial + leafRotation * 4;
}

function hideCircle(event:MouseEvent):void
{
topCircle_mc.alpha = .0;
}

function showCircle(event:MouseEvent):void
{
topCircle_mc.alpha = 1;
}

/// I also used a class file to create Mouse Over effect. If you need that file, email me...

Saturday, July 25, 2009

Door2DoorDineInn:Home Page - Heuristic Evaluation

The site has some good qualities to it. Being able to search by restaurant or cuisine. Giving different types of ordering options. Customer's feedback and newly added restaurant.

The first thing that I noticed about the web page is that the homepage has a fold. More than 70% of a time viewer don't see the content below the fold. In this case, "customer feed back", "cuisines", "delivery cities", "newly added restaurant" and "share what you think" is not visible by most viewers.



How can we solve the issue.... lets start from the top, the header doesn't need all that space. It can easily be fitted on half the size. The "Mirror Effect" is cool but not good for a logo. The phone no and fax font size can be small and bold rather than italics and big.


The Navigation bar can be little smaller, probably 75% of the size. And with regular text rather than "italics" text. If you really want to make it different than make it all caps. When you "Mouse Over" the link, it has some effects. The effects looks like something wrong with script rather than an intentional effect.


"Door 2 Door Dine Inn provide customers the luxury of enjoying fancy cuisines without leaving the comfort of their home. We are an online food ordering service that delivers delicious meals from diverse range of local and out of town restaurants to your doorstep. Our online system gives our customers access to their favorite restaurants with just few clicks from the interactive menus provided."

The information is great but how many times do I want read this information.
Obviously not every time I visit the website. So why is it the first thing on the website. What is the main purpose of visiting the site? I want to order a food from my favourite restaurant or a type of cuisine tonight as soon as possible. I also want to know if there is any special going on in any restaurant.

I think a 3 pane design works for the site.

First Pane:
  • Log in information can be put on the left hand side with design like CitiBank where SignIn and Register in same place.
  • Search Function
  • Browse by cuisine
Second Pane:
  • Hours of Operation
  • How to Order
  • Delivery Cities

Third Pane:
  • Newly added restaurant
  • Customer feedback

The search button is good but by default you have to "select" a cuisine or restaurant, which adds another click. Make one of them a default based on what customer uses the most.

oo and the site name is good but the URL is too long. If possible try to get small URL like ddDineInn.com or DDDInn.com or something short.