Google Play Services - Room - CreatorID Not Unique - android

Is it just me or is the getCreatorId() method in Room not unique for automatch games?
I have some logic in my game that is based on a unique entity deciding things, such as which player belongs on which team. Each client waits to receive this information from the 'host' (which is the room creator in this case) before launching into and setting up the game.
#Override
public void onRoomConnected(int status, Room room) {
// Game Lobby is full
if (status != GamesClient.STATUS_OK) {
return;
}
this.room = room;
// Assign the players teams
if (room.getParticipantId(activity.gameHelperManager.gameHelper.getGamesClient().getCurrentPlayerId()).equals(room.getCreatorId())) {
// Some logic here
activity.androidManager.sendMessage(Data Sent Here);
activity.game.startGame(GameType.MULTIPLAYER);
}
}
On the other side of things:
#Override
public void onRealTimeMessageReceived(RealTimeMessage message) {
// Get Message from host about game specific properties is here
if (data.contains(Message Tag Here)) {
// Parse information
activity.game.startGame(GameType.MULTIPLAYER);
}
}
However, each client views itself as the host in the onRoomConnected() method during an auto-match type game.
Is there a solution to this or am I missing something fundamental?

Admittedly, our documentation is a bit misleading (I'm requesting a fix right away), but here's the explanation of what went through our heads when we designed this :-D
What automatching really does is connect different rooms created by different people, and making them into virtually one room with everybody in it. So different people in the room may have a different idea of who was the room's creator. So using the room's creator as a way to decide who goes first is generally not a good idea.
Using the participant ID directly isn't a good idea either (because someone with a lexicographically very high participant ID would find themselves going last on every single game they play).
Please see my answer to the following question for more ideas on how to decide who goes first:
How to decide who is the first player when user plays quick game?

Related

Combining Multiple API Request Simultaneously using Retrofit and RxJava

I'm currently developing my android app and have a problem in displaying data retrieved from API in my Home Activity. Here is design for my Home activity.
On that page, I want to show three data: Latest news, most popular news, and categories. Each of the data obtained from different API. So, there are three API request when displaying the data.
The scenario that I want is to perform all requests simultaneously, showing a progress bar when taking such data and dismiss the progress bar when all of the data from such three API is successfully obtained. If I've got the latest news data, the progress bar wouldn't be dismissed until popular news and categories data successfully obtained. And when the latest news data and categories data successfully obtained, but I've got a problem when getting popular news, then all the data wouldn't be displayed on the page, and the page will display an error message.
I'm using retrofit in accessing my API. I've also tried combining it with RxJava for accessing the API. I've tried to use RxJava combine sequences method like combineLatest, merge, but the problem that I found is that it can't combine more than two requests/sequence at the same time. So I haven't met the solution.
Is there any good solution for this case?
My initial (incorrect) answer is struck through below. Apologies for the inaccuracy.
combineLatest does appear to do what you'd like. A current comment under the question has the right idea, but I think the handling of the emission of combineLatest can be done slightly better, so here is my take for that.
Observable.combineLatest(
api.getLatest(),
api.getPopular(),
api.getCategories(),
NewsReaderViewModel::new)
// This is very simple progress bar logic, and will actually break if this code
// errors. Handling of the progress bar should be slightly different, but for the
// sake of this example, I'm going to keep it as simple as possible.
.doOnSubscribe(disposable -> loadingProgressBar.setVisibility(View.VISIBLE))
// Depending on your requirements, you might not need to continue observing this
// stream. If you expect your results are going to continue to be updated, then
// you won't want to add this next line, but I don't imagine this data is going to
// live update.
.firstElement()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::displayResults, out::println);
I created the NewsReaderViewModel to hold the results, as you may want to perform some logic on the results, and couldn't do that in a reasonable way when using the ArrayList solution. Here is the NewsReaderViewModel class. It is very simple and just contains three lists of Strings.
static final class NewsReaderViewModel {
final List<String> latest;
final List<String> popular;
final List<String> categories;
NewsReaderViewModel(List<String> latest, List<String> popular, List<String> categories) {
this.latest = latest;
this.popular = popular;
this.categories = categories;
}
}
I've omitted the rest of the code, but here is a link to the Github repository with the full example that you'll be able to clone and run. Let me know if you have any questions and I hope this helps!
Here is the Github link
I'll also upload a YouTube video of the thought process behind the answer and link that video once it's available. Sometimes it's even more seeing the thoughts and mistakes and process behind the answer rather than just the answer itself.
I think you may actually want to use zip rather than combine latest. Zip will wait until all of the zipped observables have emitted once. That sounds closer to your requirements.
Here is the documentation for zip: http://reactivex.io/documentation/operators/zip.html
You'll subscribe to the resultant stream of zip and will display the results of the UI there and hide the progress bar. If you use combineLatest, you'll have to check in the resultant subscription whether or not the contents are null, and that is not idiomatic Rx

better explain couchbase lite map function rules and common mistakes

I am new to couchbase and I am trying to implement couchbase lite in one of my Android applications. What i am struggling with in particular is the concept of views and the rules for the map function as stated in the docs.
In the database the app stores documents with various doc types. In one query i need to get the entire document by document type ("payments")
and by value of an attribute of the document (doc["approved"] = true)
Hence I would create a view like so:
com.couchbase.lite.View view = database.getView("payments");
if (view.getMap() == null) {
Mapper map = new Mapper() {
#Override
public void map(Map<String, Object> doc, Emitter emitter) {
if (doc.get("type").equals("payments") && doc.get("approved") == true) {
emitter.emit(doc.get("name"), doc);
}
}
};
view.setMap(map, "1");
}
Note that the doc["approved"] value can be updated over time. In one of the rules about map functions in the docs it says:
It must be a "pure" function: ... That means any time it's called with the
same input, it must produce exactly the same output.
Would the implementation of the map function as show above violate that rule?
In the docs it further says :
In particular, avoid these common mistakes: ... Don't make any assumptions
about when the map function is called. That's an implementation detail
of the indexer. (For example, it's not called every time a document
changes.).
Does that mean when the approved status of one of the documents is updated from false to true that the following query not nessesarily contains the updated document? If so what would I need to do to achieve this? I am quite uncertain about what rule that exacly means? Could anyone try to open my eyes please?
What "pure" means is that you cannot use outside state in your map function. All your determinations must be based solely on the parameters that were passed into it. Your map function does not violate this.
I think the missing piece in your understanding is the difference between storage and indexing. You can store revisions of a document to the database, right? That in and of itself will not cause the view's index to be updated. That's what the documentation means by "not called every time a document changes." The index will be updated by default when the next query is run, so the newest state of the document will be output. It could realistically have been changed many times since the last query was run.

Monitor a range of Beacons

I want to monitor a range of beacons using Estimote. For example lets say that ("rid", "uuid", , ) identifies a series of beacons, where all the beacons my app uses share the same "rid" and "uuid". I also hace a number of brands, where each can have more than one store.
This app would be sold to a number of brands, and I would like to use something like this:
private static final Region ALL_STORES_REGION = new Region("rid", "uuid", BRAND_ID, null);
beaconManager.startMonitoring(ALL_STORES_REGION);
Then, to receive notifications when a customer exits a certain store:
beaconManager.setMonitoringListener(new BeaconManager.MonitoringListener() {
#Override
public void onEnteredRegion(Region region, List<Beacon> beacons) {
// do nothing
}
#Override
public void onExitedRegion(Region region) {
listener.onCustomerLeaving(region.getMinor());
}
});
This is what Im using right now, and its working fine. The problem is that since I used a null as the last value in the Region (in order to capture any store of that brand), the region returned by the onEnteredRegion method returns null, and Im unable to identify the specific store.
I thought of two possible solutions:
Saving the list of beacons return on the entering, and retrieving the store's id when the customer leaves. (This could be dangerous, if there are more than one beacon in range)
Or, monitoring a number of specific Regions using the store ids. (This would involve knowing all the stores Ids, so again not an ideal solution)
I was wandering if there was any way to get the actual Beacon that triggered the onExitedRegion method, or any other better solution.
Thanks!
You have two options:
Start ranging when you receive onEnteredRegion callback. From ranging you get back beacons around you so you can identify a store/brand.
Take a look at second parameter (beacon) in onEnteredRegion. According to docs:
beacons - List of beacons that triggered onEnteredRegion event. This list may not reflect all beacons around that are matching given region.
You can use this information to identify store/brand.

Inquiry google game services for current matches

I'm implementing turn based game services for a simple game:
https://developers.google.com/games/services/android/turnbasedMultiplayer
I'm using the GameHelper class from basegameutils as recommended.
I want to save some data that isn't relevant (statistics) so I don't want to sent it between players. I'm saving this data locally (sqlite) linking it with TurnBasedMatch.getMatchId().
What I need to know is how to inquiry google game services (I guess via GameHelper) which are the current matches for the signed player, so I can delete old local data.
Thanks.
Looking better at documentation I finally found a solution for that.
If your activity extends from BaseGameActivity you can do the following:
Games.TurnBasedMultiplayer.loadMatchesByStatus(getApiClient(),
TurnBasedMatch.MATCH_TURN_STATUS_COMPLETE,
TurnBasedMatch.MATCH_TURN_STATUS_MY_TURN,
TurnBasedMatch.MATCH_TURN_STATUS_THEIR_TURN)
.setResultCallback(deleteNotPresentMatches);
using your own call back, for example:
private ResultCallback<TurnBasedMultiplayer.LoadMatchesResult> deleteNotPresentMatches = new ResultCallback<TurnBasedMultiplayer.LoadMatchesResult>() {
public void onResult(TurnBasedMultiplayer.LoadMatchesResult r) {
//whatever you want, in my case delete local data for old matches
}
};

Description for google play game services Match

I'm implementing a game with turn based multiplayer with google play game services:
https://developers.google.com/games/services/android/turnbasedMultiplayer
My game has some different variations and in order to help users choose easily from the default UI, I would want to add a name for each match.
If it was possible, a player with for example 2 current matches would be able to identify each one easily without opening it.
Thanks.
You could put this information into your Turn data. Like this...
// This is the byte array we will write out to the TBMP API.
public byte[] persist() {
JSONObject retVal = new JSONObject();
try {
retVal.put("data", data);
...
You could then write a custom function to retrieve the match data and you would have to put that information into a custom inbox dialog. I have not done this currently...
This functionality is part of the standard product. Look at the sample from google skeletonTBMP.java and also the skeletonTurn.java (I think it is called). This is where you pass data between turns. It would be fairly easy to populate this into the "data" object which gets updated at each turn, and then display this value on the screen as text. Link here...
https://github.com/playgameservices/android-basic-samples/tree/master/BasicSamples/SkeletonTbmp/src/main/java/com/google/example/tbmpskeleton

Categories

Resources