Research, Dev, Share

Become Master of XCode (part 2)

Posted in Objective-C, Software Development by Khang Vo on September 27, 2010

I recommend you to have some few experience with XCode before trying to touch some of the techniques here, especially code generation because it may contain subtle bugs and if you are just a newbie, it is not easy to solve. You may also want to take a look at my first part: Become Master of XCode
Many of the techniques are learnt from “Becoming productive in XCode”

3/ Code Generation Scripting

The most common and boring problem that iPhone developers usually have is writing again and again: private instance variable, @property, @synthesize and then dealloc. It is not just boring but also easy to make mistake. Currently, I found that there is a useful way for developers to generate all @property, @synthesize and dealloc based on the instance variable.

Go into User Script, create your own group and script name:

Copy the script from Github (thanks to AllanCraig) and put into. Don’t forget your hot key to trigger the code generation. You may also need to configure the script a little bit to fit your own purpose and coding convention

4/ Code Template (Text Macros)

They have 2 main kinds of code templates: the built in text macros and your text macros:

a/ Default Text Macros:

Xcode already includes lots of text macros like: init, dealloc, fore (for each), fori (normal for loop over array). See a long list in XCode Completion Macros.

Here is the path for the built in Text Macros:

/Developer/Applications/Xcode.app/Contents/PlugIns/TextMacros.xctxtmacro/Content/Resources/

b/ Your own Text Macros:

You can put more Text Macros into Xcode by understanding and writing the Text Macros yourself. The file location for your Text Macros is: ~/Library/Application Support/Developer/Support/Xcode/Specifications

Here are some samples Text Macros that I will work through to get you the feeling of the Text Macros. I hope that after I exlain it, you can create your own.

{
  Identifier = objc.dealloc;
  BasedOn = objc;
  IsMenuItem = YES;
  Name = "Dealloc Method Definition";
  TextString = "- (void) dealloc$(BlockSeparator){\n\t<#!deallocations!#>
\n\t[super dealloc];\n}\n";
  CompletionPrefix = dealloc;
}

Identifier : the id of your method

BasedOn : the programming language of your macro. Here is objc

Name : a descriptive name

Text String: the text string will replace your Macros:

${BlockSeparator} :  the way you specify the spaces in your code, you can configure it through terminal and script

<#!deallocations!#> : a placeholder with the text deallocations.

[super dealloc]; : the text appears in your macros

5/ File and Project Templates

You can change your file and project templates, there is not much to say here. You have a built in project and file templates in:

/Developer/Platforms/iphoneOS.platform/Developer/Library/Xcode/Project Templates

/Developer/Platforms/iphoneOS.platform/Developer/Library/Xcode/File Templates

But you should create your own file and project templates in:

~/Library/Application Support/Developer/Shared/Xcode/Project Templates

~/Library/Application Support/Developer/Shared/Xcode/File Templates

You may want to copy some from the default templates and modify. The reason that you should put in your own folder is that if Xcode is upgraded, it will not delete your modification

Reference:

http://cocoawithlove.com/2008/06/hidden-xcode-build-debug-and-template.html

Become Productive in Xcode

Advertisements

iPhone App Performance Optimization

Posted in Algorithm, Iphone, Performance, Software Development by Khang Vo on September 13, 2010

iphone performance

Working in a power limited environment like mobile, and especially, iPhone here, we soon have to face with performance problem in many different kinds. Different than the web model where web front end (javascript) do some (usually not much) processing – also browsers support you a lot, iPhone native application usually has to do quite a lot of processing.

Image Source

For iPhone native app, you cannot add any hardware to help you to have better performance. The only way you can try to deal is to deal with the software code itself. I will list some few problems and solutions that I figure out these days when I really focus on optimization. The list is applicable somehow to other mobile areas like Android or limited environment like embedded device

1/ Benchmark

It is a really traditional advice, but you always have to remember to benchmark your code, even by using simple tools like NSLog or Instrument tool. You should only care about places that is slow in terms of your test rather than trying guess and error possible places.

2/ Test on iPhone device

This is another traditional advice but people usually forget. You have to test on the real iPhone device. Let me give you an example: on my iPhone simulator, a method runs within 1 second, but in my iPhone device, it takes 8 seconds, a huge difference.

So, when you test your app on the iPhone device, don’t just test for UI, memory or features that the simulator doesn’t have. Remember testing the performance as well.

3/ Multithreading and the main thread

Some people may come to you and tell you that iPhone device just has 1 core and you never need to care about multithreading. It is just WRONG.  You still need to do a lot of multithreading to reach a good level of optimization.

The main thread will do the user touch event handler and view rendering. Then, if you use the main thread for some calculation that takes a lot of time then your UI just become frozen or not smooth when you scroll.

For UI like UITableView where users scroll between many cells, the runtime will run a loop over visible cells and set the contents. Because this process runs in a row not concurrently, and it will not allow you to view or scroll the UITableView until it returns all cells, you can possibly let some of the cell content run on another thread. (more about performance on UITableViewCell part).

The other reasons for using thread are well-known, heavy IO and network processing, all of them block processing and you need thread so that your main thread is not block

But, be CAREFUL, Multithreading comes with its own disadvantages. For rendering the view, you should do it on the main thread or somtimes, your app will just crash randomly. Another traditional reason is that the CPU has to switch too much between threads and it takes more time than usual to finish a task

4/ Use Memory wisely

Some questions on stackoverflow that I sometimes see shows a scare feeling about memory. It is right that iPhone has limited memory but it doesn’t necessarily mean that you should use it as least as you can.

The right mind you need to keep is using that limited memory smartly. We all know the priority of speed is Memory > File and Local IO > Network, the fastest access is always using memory cache for the data. There are some problems for memory caching in iPhone:

    – You have to respond to 1 method in every UIViewController:  (void)didReceiveMemoryWarning. In this method, you have to smartly release some memory cache of data to reduce your memory usage. 

    – Know what/when to cache something in memory. There are lots of Caching algorithms outside from simplest ones like: Random Replacement, Least Recently Used, Most Recently Used. It is also an issue of caching big images or caching lots of small images. It all depends on your app. For my app, my main view contains lots of thumbnail images that need displaying fast and the user can wait for seeing big images. So, we cache a lot of images (60-100) for just 2 MB of memory.

5/ Algorithms and Data Structure

For my case, I didn’t really need to solve big performance issue with Algorithm and Data Structure, but in a limited environment, a small mistake may lead to a big deal and hard to detect. My case was that I need to merge 2 data arrays from the network using some unique characteristics of elements.

The app works really well in the Simulator for about 50-100 for each array (less than 0.5 second) . However, when I tested on the device, the time surprised  me, 8 seconds (16 times slower). It cost me 1 hour to detect that I use 2 for loops through 2 arrays which means O(n2), and then, I changed it to a dictionary which reduced the algorithm to O(n) and took me back to 1 second.

What I learnt here is that even we don’t ever need to deal with Massive Data, we still need to be careful about some algorithm and data structure. 50 elements are nothing in a desktop or server scale but can cause a huge issue on limited environments in iPhone. Another lesson is a remind for me that I should always test on the real device

6/ Reuse Cell (UITableViewCell)

This part is quite unique for iPhone but may be good for other people to learn. In iPhone, we have a concept of UITableView for displaying a list and a table can contain a lot of cell.

The problem is that rendering the Cell (or generally the UIView), takes lots of time and can cause the app to look like stuck when it is scrolling. Usually, if you use the default UITableViewController template, the template already gives you the code for reusing the UITableViewCell.

The only problem is when you create a custom UITableViewCell using some usual tutorials like this and this (especially using Interface Builder), they forget to tell you that setting a CellIdentifer in the UITableView is not enough to reuse a cell. What you need to do is to set it in InterfaceBuilder or write a method to return it. I know that many people will forget it and think that they still reuse the cell, but they don’t. I suffer the same problem until I did benchmark and found the problem recently.

Here are 2 good techniques:

Copied from Stackoverflow, this question:

1st way: Just implement a method with the appropriate method signature:

- (NSString *) reuseIdentifier {
  return @"myIdentifier";
}

2nd way:

How to Reuse a Cell in Interface Builder

References:

1/ Web Caching, wikipedia

2/ Web Caching, Stanley Luong’s course material

3/ Stackoverflow – reuseable Cell

4/ Stackoverflow – custom UITableViewCell

Become Master of Xcode

Posted in Iphone, Learning, Objective-C, Software Development by Khang Vo on August 26, 2010

For iPhone development guys (and Mac as well), we all want to be as productive as possible. And one of our important tools is Xcode. I can even say that if we can master of Xcode, we can double our productivity. The reason is not only the time that the tool can save us but the number of times it breaks our workflow, or make us become bored/tired of our jobs. We are all humans, and no human in the world wants to do the job that a machine can do. Ok, stop talking and I will show you my summary of tips/tricks and techniques that I feel very very useful for me.

Many of these tips is from this stackoverflow post (I just list what I feel is most productive), 2 famous videos called “Becoming productive in XCode”, and a famous cheat sheet that almost all of us know “Complete Xcode Keyboard Shortcut List

I also recommend you to go there and take a look because this post may be really personal and lack excellent tips that you want.

1/ Basic Hot Keys

File Cursor Movement

  • Header/Source File Switching: Option + Command + Up Arrow
  • Last cursor point switch back and forward: Option + Command + Left (Right) Arrow


Quick Help/Documentation

  • Jump to Definition of a symbol : Command + Double-Click on a symbol
  • Find Text in Documentation of a symbol: Option + Double-Click on a symbol: (Only works if you have they symbol’s Doc Set installed.)


Auto Complete

  • (previous) next auto-completion argument : (Shift) + Control + /
  • Auto completion pop-up list : Escape or Control + comma
  • (previous) next Auto completion choices movement: (Shift) + Control + period


Text Movement:

  • Cursor movement between words : Option + Left (Right) Arrow
  • Cursor movement camel-cased parts of a word: Control + Left (Right) Arrow
  • Beginning or end of line: Command + Left (Right) Arrow


Interface Builder:

  • Jump to class in Xcode : Command + Double-click on an object in Interface Builder’s
  • Drag a customized object back to Interface Builder’s Library for later reuse.
  • Object overlap, see object menu under mouse: Control + Shift + Click on an object :


Code Organizing:

  • Bold line in the function list: #pragma mark Foo
  • Auto complete the pragma: pm or #p
  • Notation convention: // TODO: or // FixMe
  • Commenting a line: Command + /


2/ Advanced Hot Keys

With advanced hot keys, you will rarely need to use the mouse. Because, everything you need to do with the mouse, you can do it with the hot keys.

  • Open File Quickly : Command + Shift + D and don’t forget that open quickly uses the current word as a search term.
  • Popup list of methods and symbols in the current file : Control + 2
  • Look up current symbol:  Control + Command + ?
  • Editor area to full screen : Command + Shift + E
  • Debug and Editor Mode switch in All-In-One XCode mode : Command + Shift + B


3/ Some useful scripting

I will tell you more about scripting in the next part, but currently, I think this list is basic enough:

Default Auto Completion list, show when you type

defaults write com.apple.Xcode XCCodeSenseAutoSuggestionStyle List

Turn Off Undo Warning

defaults write com.apple.Xcode XCShowUndoPastSaveWarning NO

Git auto and tips (windows + OS X)

Posted in Open Source, Operating System, Software Development, Version Control, Windows by Khang Vo on July 20, 2010
Git auto and configuration

Git Configuration Tips

1/ Configure git with your identity and colors:
To make some identity and colors change, type this line in Terminal:
vi ~/.gitconfig
Then enter (put your name instead of mine)
[user]
name = Khang Vo
email = vodkhang@gmail.com
[color]
ui = auto
2/ Git alias
You can also define some git aliases for the shell command line by doing vi ~/.gitconfig
Enter these lines (these aliases are just my suggestions — you can change it if you want, but here is my preference)
[alias] st = status ca = commit -am br = branch co = checkout lg = log -p au = add -u l = pull s = push
Reference:
https://git.wiki.kernel.org/index.php/Aliases

3/ Bash shell auto-completion

In Windows, auto completion is by default, in Mac OS, you have to manuall set it up to have auto completion. These steps will help you to have an auto complete git on your MAC machine. It also display the current branch when you are in a git repository.

cd /tmp
git clone git://git.kernel.org/pub/scm/git/git.git
cd git git checkout v`git --version | awk '{print $3}'` cp contrib/completion/git-completion.bash ~/.git-completion.bash cd ~ rm -rf /tmp/git echo -e "source ~/.git-completion.bash" >> .profile
vim .profile
Put the following line
PS1='\u@\h:\W$(__git_ps1 " (%s)")\$ '

Then restart your terminal

Reference: http://denis.tumblr.com/post/71390665/adding-bash-completion-for-git-on-mac-os-x-leopard http://www.codethatmatters.com/2010/01/git-autocomplete-in-mac-os-x/

4/ Pull/Push auto-completion

By default, the git pull auto complete will contact with server. If you want to make auto-complete always complete using local branch names, then you can change the behavior.
This might only be useful if your local branch names are identical to remote branch names.

Edit the file
~/.git-completion.bash and around line 458, look for this code:

fetch)
if [ $lhs = 1 ]; then

        __gitcomp "$(__git_refs2 "$remote")" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    fi
    ;;
pull)
    if [ $lhs = 1 ]; then
        __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    fi
    ;;
push)
    if [ $lhs = 1 ]; then
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
    fi
    ;;
esac

…and change it to this:

fetch)

    if [ $lhs = 1 ]; then
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
    fi
    ;;
pull)
    if [ $lhs = 1 ]; then
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
    fi
    ;;
push)
    if [ $lhs = 1 ]; then
        __gitcomp "$(__git_refs)" "$pfx" "$cur"
    else
        __gitcomp "$(__git_refs "$remote")" "$pfx" "$cur"
    fi
    ;;
esac

(Notice that we changed the “fetch” and “pull” sections to use the same logic as “push”. This means it will be looking for local branch names instead of remote branches.)

Reference: http://superuser.com/questions/137689/git-pull-auto-complete-osx

iPhone development tools

Posted in Iphone, Software Development by Khang Vo on June 28, 2010

Working with Iphone development is working with OSX, and we always need good tools and software for both IPhone and OSX environment to boost our productivity and reducing the repetitive, boring jobs

1/ Multitouch, Accelerometer and more : ISimulate

An application allows you to use your real iphone to control the IPhone Simulator. There is nothing better than the real IPhone device to get the real user feeling. The reason is that it will save a lot of time for you when you only build on simulator, debugging on simulator and you have a wide screen to see.

2/ Memory static analyzer : Clang

Help you a lot in the managed memory environment of iphone development. Good news is that the new XCode (3.2) will integrate directly with Clang help you to analyze and find memory leak much faster.

3/ Google tool box for Mac

You cannot write a good iphone app development without writing good unit testing. And I suggest you to use Google toolbox for Mac with a lot of supports, easy to integrate into your project. It is better than the default OCUnit in XCode. It also really runs your code, which takes more time, but gives you a real, better result and can help you to deal with some File IO or real code you need to run when running unit test.

4/ UI Automation Test: XCode Instrument

Stop running the UI everytime you fix a bug or adding new feature. UI Automation Instrument is a best tool for you like robot proxy in web testing.

5/ Screen capture software: Jing

Good, free software with high quality captured video. Good use for demo.

Catupre Screen Software

6/ Chat client: Adium or Imo

Why do I put a chat client here? Everybody need some way of communication, especially if some of your co-workers or clients are not there. In Mac, you can use Adium to integrate a lot of chatting services like Gmail, yahoo…

Some thoughts on open source and the openness

Posted in Open Source, Software Development by Khang Vo on June 12, 2010

After learning and discussing to developers around me, I have some of my thoughts on open-source world and the more general one, the openness of the world. I will try to walk through some posts about this issue to discuss around those things. From now on, I will use open source software as a general term for open source software, library and framework. The viewpoint is quite based on start up environment.

1/ What is open source?

Open source software is software that allows people to view the source code, to change, to modify or to link it (library, framework) with your software or system to build a new, bigger or better one.  It really depends on the license of the open source that I will list and discuss some of them later.

2/ Open Source Users’ benefit?

In short, it can be quoted by Newton:”If I have seen further it is only by standing on the shoulders of giants” (http://www.cippic.ca/open-source/). Open source software development embraces this principle.

  • No buying cost => can try and fail then try another easily. (but it is not free, read the disadvantage part)
  • When there is an error, everybody knows and tells it out.
  • If you work with something really new, nobody else works on that before or no library reaching to the point that is acceptable to your application. You will know how much important it is to allow you to modify and extend a library. Famous companies will not take a big risk to go ahead in risky and new area to support you.
  • Can be already tested well by the huge community if there is a bug, people can find it already for you, already posted a patch for you.
  • Community Documentation is also a benefit when many people already asked and answered about the software.

3/ Any risk or drawbacks?

  • Not all the open source software is good. Those open source software require a lot of testing from community. You may sometimes take a big risk yourself. My team already experienced some stupid bugs from an open source library. There is no 100% guarantee. If you buy some service/framework/library, you can sue them for the bad quality.
  • “Linux is free, if your time has no value” is correct no matter how you love Linux. You have to pay time for learning it, for testing the new library to make sure it runs like it is declared.
  • Many open source software is really bad at documentation. Some people create open source software just for fun, so they sometimes are not expert, not professional and not responsible enough to document it well.
  • The open source software can become out of date at sometime. When the authors start getting bored about their products and become too busy, they just don’t update it frequently. I have quite few experiences on open source software development, but I can see that all software need a leader, it can be an original author or can be any other people. It can be right that the whole community can contribute. However, if the software has no shared vision to grow or no people make sure that it keeps growing, it will become out of date soon

3/ Licenses of Open Source

Now, I will move to the next part, which somebody may still misunderstand about it, the license. I will move from the most generous license to the strictest license. The license will really determine how we can use the open source software, varying from almost open like you can copy and redistribute it to really strict like you can only link to the library

Absolutely open, you can distribute, recreate, copy using whatever means you want.

Like public domain, but with a little bit more restriction: the name of its contributors is not allowed to be used to promote the software use the open source. Both of them have a little bit difference that you may want to read more yourself.

  • GNU GPL General Public License

This one is like BSD and Apache but it is stricter. If you modify the copy/copies or a portion of it, use it or distribute it, your program MUST BE under the GNU GPL.

It is GPL but with less strict. It means, if you modify the program, you still have to distribute your work under the same license. However, if you just use the open source program like a library (which means you link to it by source and compiled code), you are allowed to distribute your program

4/ References and additional Materials

Software Engineering Process and Tools lecture, Quang Tran

http://www.informit.com/articles/article.aspx?p=376255

http://www.tamingthebeast.net/articles5/open-source-software.htm

http://googleblog.blogspot.com/2009/12/meaning-of-open.html

http://www.cippic.ca/open-source/

http://en.wikipedia.org/wiki/BSD_licenses

http://www.apache.org/licenses/

Anonymous class Java

Posted in Java, Programming Language, Software Development by Khang Vo on June 6, 2010

Some days ago, when answering a question on stackoverflow , I just recognized that I didn’t understand much about anonymous class in Java. Maybe I am not the only one, so I post it here. I think this should be in some book already, but by my bad, I didn’t read it well.

Ok, here is a simple question on stackoverflow:

    public static void main(String[] args) {
        System.out.println(
          new myClass() {
             public String toString() {
               return "myInterfacetoString";
             }
           });

        System.out.println(
          new myClass() {
              public String myFunction() {
                return "myInterfacemyFunction";
                }
          });
    }
and the user asked why the output is:
myInterfacetoString
primitivedemo.Main$2@9304b1

It is extremely easy, right? Because you override the method toString() of the Object class. But then, the questioner asked more: how about change from new myClass() –> new myInterface() with some interface myInterface already declared, what would happen?

My first thought is that the class name of the anonymous class is not necessary and having no relationship with the real class, interface sharing the same name.

But I just remembered about some of my snippet code before with

new Runnable(){

@override

public void run() {}

}

will behave well like a runnable object

So, what is a correct way of anonymous class. After asking Google, I found a good link about it:

http://www.developer.com/java/other/article.php/3300881/The-Essence-of-OOP-using-Java-Anonymous-Classes.htm

There are 2 main important points:

new className(optional argument list){classBody}

This expression instantiates a new object from an unnamed and previously undefined class, which automatically extends the class named className, and which cannot explicitly implement any interfaces. The body of the new class is given by classBody.

The result of executing this expression is that a new class that extends className is defined, a new object of the new class is instantiated, and the expression is replaced by a reference to the new object.

new interfaceName(){classBody}

This expression instantiates a new object from an unnamed and previously undefined class, which automatically implements the interface named interfaceName, and automatically extends the class named Object. The class can explicitly implement one, and only one interface, and cannot extend any class other than Object. Once again, the body of the new class is given by classBody.

Logging class/method/variable name in Objective-C

Posted in Objective-C, Programming Language by Khang Vo on May 5, 2010

Just a small post for an effective tip in Objective-C.

Usually if you use the

NSString *name = @”Hello World”;

NSLog(@”%@”, name);.

Output: Hell world

And usually, when we debug the program and viewing the log, we really want to know the class/method/variable name and line number as well. You can manually hard code it like

NSLog(@”ApplicationDelegate – applicationDidFinishLaunching – name – Helloworld”);

But, it is really time consuming and repetitive task. For our company, we use


#define NCLog(s, ...) NSLog(@"<%@:%s:{%d}> %s = %@",
[[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
 NSStringFromSelector(_cmd), __LINE__, #__VA_ARGS__ , \
 [NSString stringWithFormat:(s), ##__VA_ARGS__])

Another variant of this is (it combines both class name and method name into __FUNCTION__):

#define NCLog(s, ...) NSLog(@"<%s:{%d}> %s = %@", __FUNCTION__, __LINE__, \
 #__VA_ARGS__, [NSString stringWithFormat:(s), ##__VA_ARGS__])

Then you can just use it like NSLog. For example:

NCLog(@”Hello world”);

Output: <ApplicationDelegate:applicationDidFinishLaunching:100> name: Hello World

Good luck to your new productivity:). For your programming language, stop using the System.out.println() and Console.WriteLine, find a version of yourself

References:

http://stackoverflow.com/questions/2770307/log-the-method-name-in-objective-c

http://stackoverflow.com/questions/2818542/print-out-the-variable-name-objective-c

RoboCode Team Battle (Week 4)

Posted in Algorithm, Competition, Intelligent System, Learning, Robocode, Software Development by Khang Vo on April 21, 2010

Hi, everybody, the robocode competition goes up to another level, promising more fun and more jobs for you guys. We just released a new rule this morning requiring people to compete in team, 2-2 battle. The era of 1-1 battle ended. This morning is just a practice for a new game. You do not have time to improve your robot a lot, that’s ok now. You just need to have a better communication with your ally.

Now, we just take a look at battles between 2-2. There would only have 4 teams this morning but creating a lot of fun and entertain for people. Poor you guys, the people not joining this morning

The first match:

The Red and the Blue guy on the same team while the White and Black on the other team. The match was quite in the first team when the Black guy use the still strategy, which was good for some robot cases that can not shoot the still robot

The second match:

The 2 yellow guys compete with Gray and Blue guy. The 2 yellows shoot quite correctly but the strategy of the other team is against the Yellow team when they move in line but change direction really fast.

The third match:

We found the anti-Indian guy. Welcome to Yellow guys, you guys did a really well job when running in a spin strategy and the Indian strategy almost dies.

[youtube=http://www.youtube.com/watch?v=y8o4WxNhMKw

Wait for tomorrow, when we will have a real team battle. Never have the case that we will shoot each other any more. And AWARDS, will officially be given for the first 2 teams tomorrow.

RoboCode Report Week 2

Posted in Algorithm, Competition, Intelligent System, Learning, Robocode, Software Development by Khang Vo on April 3, 2010

And now, we are already on the week 2. Different than week 1 when I am too busy to write some brief report. I will write some brief report, feedback and evaluation about the second competition.

First, come to the battle between Police and Indian. We can see that Police does not have a big improvement over the last week, while Indian goes into the next level by getting the ideas of running around the opponents from his own opponents (ideas started by Police). We also wait for some peole to kill that suck Indian. Everybody really wants to kill the Indian

Then, we come to the next match between Tester and Rammer. Rammer tried to implements a combining strategy between Rammer, Indian and Spin Bot. But, to be honest, it was an example for what people say : “good idea, bad implementation”. Rammer tried to change the algorithm at the bad times and the RunAway strategy was not good enough. Waiting for the next version when Ramming and Indian shake their hands:D. We also welcome the new comer, a handsome guy, Phan Vo. Hope that we will see a better implementation in the next version

Yeah, now, we see how good Alosa (a loser) is and if it is a real alosa. With a quick implementation in the Web Dev class (Buu will get disappointed for that news), a new version of SweetPo has come into the world. And welcome Huy, another new comer this week. Inherits from the Indian, Huy produced a better implementation. That’s so good and fit exactly what we expect when publishing our source code. I can see a good future for Huy in later versions.