Thursday, December 26. 2013BrainKing poker club on PokerStars![]()
You are invited to join my private poker club for Home Games online.
That's it! Once I've approved your membership request, we'll be ready to start playing Home Games online together. You know, I would really like to play poker tournaments with other BrainKing members but since I don't have time to implement them myself (BrainKing poker client is just a simple attempt to make a poker table in JavaScript), it would be nice to use a stable and mature platform with a great reputation. If we manage to get enough active players, it will be possible to create regular tournaments of different types, BrainKing league etc. Anyway, it is free, so why not to try it at least. ![]() PokerStars home games Note: USA players will probably need to create a play money account here: http://www.pokerstars.net Wednesday, October 17. 2012Android - Endless dynamic ListView
Android's ListView is a great component that allows a developer to easily display simple application menus or list of short texts decorated with image icons, colored fonts etc. However, when our ListView should be populated by a big number of values, it would be a bad programming practice to load them all at once - we don't want to consume a significant part of the customer's cell phone by data and show only a small part of them (limited by the device's display size). A much more effecient approach is to load only a few rows (e.g. 20) and when the user scrolls down to the end, automatically load more and add them to the list.
Unfortunatelly there is no direct built-in support for such feature in the ListView component, so we must do a little programming work here. The code snippets are taken from my BrainKing for Android application, more precisely from the activity that displays a list of games to play. First of all, create the ListView component and its Adapter: ListView listView = (ListView)findViewById(R.id.list_view); adapter = new GameAdapter(this, R.layout.game_row, dto.gameList); listView.setAdapter(adapter); To fetch the ListView rows, we will use an AsyncTask HTTP Request pattern from our previous example. When the activity is started, it will load the first 20 games and put the to our list adapter. Very well. Now we need to be notified when the user scrolls to the end: public class GameList extends Activity implements AbsListView.OnScrollListener ... listView.setOnScrollListener(this); ... @Override public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) { boolean loadMore = totalCount != totalLoadedCount && firstVisible + visibleCount >= totalCount; if (loadMore) { totalLoadedCount = totalCount; getContent(dto.loadedCount); // call AsyncTask to load the next batch of rows from this index } } And the ListView must know that its data set has been updated: adapter.setItemList(dto.gameList); adapter.notifyDataSetChanged(); All right, let's put it all together: public class GameList extends Activity implements AbsListView.OnScrollListener, AsyncTaskCompleteListener<String> { public static int gamesPerPage = 20; private ProgressDialog progressDialog; private GameAdapter adapter; private GameListDTO dto; private int totalLoadedCount; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.list_container); dto = new GameListDTO(); totalLoadedCount = 0; ListView listView = (ListView)findViewById(R.id.list_view); listView.setOnScrollListener(this); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) { Intent intent = new Intent(GameList.this, Game.class); intent.putExtra("gameId", dto.gameList.get(position).id); startActivityForResult(intent, 0); } }); adapter = new GameAdapter(this, R.layout.game_row, dto.gameList); listView.setAdapter(adapter); listView.setItemsCanFocus(true); getContent(0); } private void getContent(int gameStart) { progressDialog = ProgressDialog.show(this, "", getResources().getString(R.string.loading_message), true, true); new HttpGetTask(this).execute("GetGamesToPlay?c=" + gamesPerPage + (gameStart == 0 ? "" : "&s=" + gameStart)); } @Override public void onTaskComplete(String result) { if (progressDialog != null) progressDialog.dismiss(); dto.load(result); adapter.setItemList(dto.gameList); adapter.notifyDataSetChanged(); } @Override public void onScrollStateChanged(AbsListView absListView, int i) { } @Override public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) { boolean loadMore = totalCount != totalLoadedCount && firstVisible + visibleCount >= totalCount; if (loadMore) { totalLoadedCount = totalCount; getContent(dto.loadedCount); } } class GameAdapter extends ArrayAdapter<GameDTO> { private Context context; private int textViewResourceId; private List<GameDTO> itemList; public GameAdapter(Context context, int textViewResourceId, List<GameDTO> itemList) { super(context, textViewResourceId, itemList); this.context = context; this.textViewResourceId = textViewResourceId; this.itemList = itemList; } public void setItemList(List<GameDTO> itemList) { this.itemList = itemList; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) row = LayoutInflater.from(GameList.this).inflate(textViewResourceId, null); GameDTO gameDTO = itemList.get(position); TextView gameLabel = (TextView)row.findViewById(R.id.list_label); gameLabel.setText(BrainKing.getInstance().getGameName(gameDTO.gameType) + " (" + gameDTO.opponentName + ")"); TextView timeLeftLabel = (TextView)row.findViewById(R.id.time_left); timeLeftLabel.setText(dto.timeLeft); return row; } } } The number of rows to load is set to 20 so each time the user scrolls to the list end, the adapter will be extended by another 20 rows until there are no data left. The loadMore condition in onScroll method ensures that getContent won't be called each time the user scrolls the game list anywhere (which triggers the onScroll event).
Thursday, October 11. 2012BrainKing for Android - alpha version![]()
I have just uploaded the first alpha version of BrainKing for Android application to Google Play, so anybody who owns an Android device and wants to give it a shot, should be able to do it.
BrainKing for Android Please note that it is in a highly unfinished state and not too useful at the moment. ![]()
I have decided to put the application to Google Play although it is far from being mature and completed. The reason is that people who want to help with testing should be able to install it quite easily and it won't be necessary to notify about new versions - Android and Google Play should handle it automatically. Saturday, October 6. 2012Android HTTP Request in AsyncTask
One thing that a developer of a client-server application faces in an early stage is how to make safe and reliable requests to the server without making the Android phone totally frozen and non-responsive to any actions. If you are new to Android development, it can turn out to be an incredible nightmare, mostly because the official examples are not too well documented (which, in fact, can be said to anything related to Android).
OK, what’s the issue? We are developing an application for a device that is supposed to do many other tasks at the same time (detect incoming phone calls, synchronize some data in background etc.), so the ActivityManager watches over running processes and kills the ones that do not respond for more than 5 seconds. Which means that if BrainKing application requests data from server in the usual way (main thread) and the connection is not fast enough, the client would simply crash. Spooky, huh? Our solution is AsyncTask implementation.First, we need our Activity to be notified when the HTTP requests completes loading all necessary data:public class Main extends Activity implements AsyncTaskCompleteListener<String> The AsyncTaskCompleteListener interface declares just one method that will be called by our AsyncTask implementation:public interface AsyncTaskCompleteListener<T> { public void onTaskComplete(T result); } Then, when we want to call the server and get the data, the following lines will do the trick (with a nice "Loading ..." spinning wheel): progressDialog = ProgressDialog.show(this, "", getResources().getString(R.string.loading_message), true, true); new HttpGetTask(this).execute(url); Now the class that actually makes the data transfer: public class HttpGetTask extends AsyncTask<String, Void, String> { private AsyncTaskCompleteListener<String> callback; public HttpGetTask(AsyncTaskCompleteListener<String> callback) { this.callback = callback; } @Override protected String doInBackground(String... strings) { String url = strings[0]; StringBuilder builder = new StringBuilder(); HttpClient client = BrainKing.getInstance().getHttpClient(); HttpGet request = new HttpGet(IOUtils.getEncodedUrl(url)); try { HttpResponse response = client.execute(request, BrainKing.getInstance().getLocalContext()); HttpEntity entity = response.getEntity(); if (response.getStatusLine().getStatusCode() == 200) { BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent())); String line; while ((line = reader.readLine()) != null) { builder.append(line).append("\n"); } } else { // handle "error loading data" } entity.consumeContent(); } catch (Exception ex) { // handle "error connecting to the server" } return builder.toString(); } @Override protected void onPostExecute(String result) { callback.onTaskComplete(result); } } Please note that we do not create a new HttpClient instance for every single request but reuse a pooled one (to save system resources), so it is quite important to call entity.consumeContent() when we are done, otherwise a exception would be thrown on the next request (for some reason, Apache HTTP client does not make the cleanup by default).So, the HttpGetTask class loads data from the server in background (thus it does not block UI thread and Android will not detect our application as "frozen") and when it is done with it, onPostExecute(String result) is called and returns data to the main activity's onTaskComplete(String result) method:@Override public void onTaskComplete(String result) { if (progressDialog != null) progressDialog.dismiss(); // parse the data here and show some results } And the helper methods to retreive objects that are required for HTTP transfer: public HttpClient getHttpClient() { if (httpClient == null) { HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 5000); // allow 5 seconds to create the server connection HttpConnectionParams.setSoTimeout(httpParameters, 5000); // and another 5 seconds to retreive the data httpClient = new DefaultHttpClient(httpParameters); } return httpClient; } public HttpContext getLocalContext() { if (localContext == null) { localContext = new BasicHttpContext(); cookieStore = new BasicCookieStore(); localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); // to make sure that cookies provided by the server can be reused } return localContext; } The 5 seconds timeout will be probably allowed to change by the user (perhaps someone with a really slow internet connection would like to wait 10 seconds or more?). Anyway, one of true parameters of our ProgressDialog instance makes the background process cancellable, so if a user does not want to wait for the server timeout (in case of connection issues), a simple back button tap should terminate it.
Wednesday, October 3. 2012BrainKing for Android![]()
As I unofficially announced a week ago, I have started to code a BrainKing client for Android phones (and tablets) and, unlike other BrainKing side projects, this time I am determined to finish it.
![]()
In fact, I am far from being an experienced Android developer at the moment because I had started to learn it just a month ago, so please do not expect me to release a full featured BrainKing application in a near future. However, some work is already completed and the first beta version could be available in … well … sooner or later, surely this year. ![]() Meanwhile, if you have an Android device, please do not hesitate to test my very first Android application and, if you like it, leave a nice review on Google Play. ![]() ![]() Thursday, April 5. 2012More Easter eggs![]()
First of all, I am very glad to see that more than 40 BrainKing users already took advantage of getting at least 10 free Brains in our Paid membership for free! promotion. This action was silently introduced a couple of weeks ago and since everybody has a great chance to receive not just free Brains (that can be used to win more Brains and finally turned to a membership subscription) but also improve own poker skills with no risk, I am sure that more and more people will find it worth trying.
And now to the subject: Easter Egg! Since the number of requests to create the Easter Action this year is quite high again, it is here and this is it. Everybody has a chance to get up to 125% bonus to a Brain Rook membership level order, based on the popular system of color codes. Let me remind the rules of this action: When you see a small flashing light bulb on the Main Page or next to Paid Membership link at the left column, you know a bonus is active and can be used. But don't hesitate for a long time - some bonuses (especially the one which adds 125% to the subscribed period) can be active only for several minutes. The bonuses can be used only if a purchased membership is for Brain Rook level and 1 year or longer period and it is not a Brains payment. This action will be active until cancelled. The day when the action ends is not specified but, regarding the Easter nature of the promotion, it should happen in April 2012. Furthermore, I would like to remind an opportunity to obtain a Black Rook lifetime membership for a fraction of its list price, if you succeed to get the Bonus conqueror achievement. Do not hesitate to take your chance. ![]() Sunday, April 17. 2011Recent changes of BrainKing features![]()
As we have announced in the Server News, BrainKing is currently under a process of optimization and tuning, in order to improve the overall performance and response time, mostly by rewriting certain functions that cause too much CPU load. There is nothing to worry about - everything is working OK and many players will probably notice no important changes. Anyway, I would like to clarify what exactly has been modified and why:
After implementing the mentioned changes, a couple of small bugs appeared, as usual:
I hope I listed all important things here. If not, please leave a comment. ![]() Thursday, October 21. 2010Separation of system messages![]()
You might have noticed a new link in the left column of BrainKing pages, called Events, just below Message Box. Starting today, all messages generated by the system (game resignation, tournament invitation, winner notification etc.) will be shown on this page, while the former Message Box would be used for personal messages only.
The reason is simple. I've made a fast lookup and realized that only 10% (or less) of all messages are actually sent by BrainKing users and it's easy to overlook them in the middle of the system ones, especially if you play many tournaments and don't visit BrainKing for 2 weeks. Furthermore, many people don't even read system messages and delete them without opening - and I cannot blame them. Sometimes, I do it too. ![]() The Events page is probably not flawless because the whole structure of system event generation has been fully rewritten, in order to make it compatible with upcoming new version of BrainKing. Any suspicious behaviour of missing functionality can be reported to the Bug Tracker, of course. Sunday, September 12. 2010One million percent![]()
Please don't take this short article too seriously.
![]() ![]() However, it still shows that BrainKing has more than 140,000 visitors a month (unique, more or less) which is surely a great number and higher than I expected. Although my respect to Google products is, uh, all kinds of good and bad (based on our experiences from the past), their Analytics tool is quite useful, providing a lot of interesting data. For instance, let's see a decreasing ratio of Internet Explorer users:
Well done, Mozilla and Google. ![]() Friday, September 10. 2010Prize tournaments redesigned![]()
I am sure that some active people who create prize tournaments on a regular basis have already noticed that, but since no official documentation has been released yet, I think it is time to produce a little clarification of the subject.
I should also note that this article is related to BrainKing prize tournaments with no entry fee (or freerolls, if I use an online poker terminology). It does not affect Brains tournaments. Well, what is actually changed?
I have noticed that a couple of people have already tested this system and nobody reported any bugs. It is a good news. ![]() Wednesday, September 1. 2010September action of Black Rooks![]()
I have been thinking, thinking and thinking of any possible improvements of our September Action that was announced in August and successfully tested as well. Improvements that would be fair to everyone.
I didn't come to any conclusion, so let's follow the test week pattern. With a small bonus.
Everything will be properly announced tomorrow. ![]() Tuesday, August 24. 2010BrainKing and IPv6![]()
I have just noticed a lost and found draft I made 4 months ago, so I have decided to publish it at last.
![]() OK, let me make a few notes:
There is one thing I really love about it. BrainKing has been already given a IPv6 range of /64 type, which means that when the old protocol is fully replaced by this one, we will be allowed to use exactly 18,446,744,073,709,551,616 different IP addresses for our projects. I guess it should be enough for even larger companies than BrainKing. ![]() Saturday, March 20. 2010A hidden login feature![]()
There are people who like to change their BrainKing user name every week, some of them even more often. Well, it is not against the rules and if they feel compelled to do it, it is only their business.
![]() The solution is very easy and it might be suitable for people who do not change their user name as well. Since today, it is possible to enter either user name or email address (which is registered with your BrainKing account) to the login form. And if you use your correct password, BrainKing should log you in. No matter how many times you modify your user name - just remember your email and you are safe forever. ![]() The "User Name" label at the login form will be probably renamed to "user name or email address" soon. Until then, it is a hidden (but useful) feature. Tuesday, March 16. 2010Easter and logo![]()
Yes, I know that BrainKing game site has its own blog and it would be nice to post some news occasionally.
![]()
There will be also a few additions to the current BrainKing in a near future, mostly because it is our good concern to reflect demands of the market (phew, what a terrible sentence). More details later. Sunday, December 6. 2009Dynamic home page![]()
Although our current home page (BrainKing) is much more detailed than the former one "white background and some short text", it still looks too static to be worth visiting for other than a login purpose. I would like to make it a little different for every single visit. For example:
Any other ideas? Actually, BrainKing's home page will be the only page that would keep the current castle design (with towers, flying dragon etc.), so it might be really nice to make it a little more attractive. And I like to collect original ideas. ![]()
(Page 1 of 41, totaling 607 entries)
» next page
|
BrainCalcMap of visitorsQuicksearchAdvertisementSorted archiveWikipedia FinderKategorieSdílení webloguBlog AdministrationHledánà na wikipedii |
Comments