Nested Cursors over two different Stores - xodus

I have following code:
...
Transaction xodusTransaction = xodusEnvironment.beginReadonlyTransaction();
Store leftStore = xodusEnvironment.openStore(leftName, StoreConfig.USE_EXISTING, xodusTransaction, false);
Store rightStore = xodusEnvironment.openStore(rightName, StoreConfig.USE_EXISTING, xodusTransaction, false);
try(Cursor leftCursor = leftStore.openCursor(xodusTransaction);
Cursor rightCursor = rightStore.openCursor(xodusTransaction)) {
while(leftCursor.getNext()) {
while(rightCursor.getNext()) {
// Do actual work with data from both stores
}
}
}
...
I expect that internal loop will be fired N*M times, where N - cardinality of leftStore and M - cardinality of rightStore.
On practice external loop fires only once and internal loop fires M-times.
If I rewrite the code in following way (flattering nested loops):
...
while(leftCursor.getNext()) {
...
}
while(rightCursor.getNext()) {
...
}
...
Then both loops fires as expected N-times for leftStore and M-times for rightStore.
The question is: is it possible to make nested cursor traveling? If yes, kindly please guide me.
Thank you!
-Taras

Once cursor.getNext() returned false (there is no next key/value pair), it will never return true for this Cursor instance. To traverse a Store again, reopen cursor.
Here is the code traversing two Stores as a matrix, i.e. all pairwise combinations of key/value pairs from both Stores:
try (Cursor leftCursor = leftStore.openCursor(txn)) {
while (leftCursor.getNext()) {
try (Cursor rightCursor = rightStore.openCursor(txn)) {
while (rightCursor.getNext()) {
// Do actual work with data from both stores
}
}
}
}

Related

Comparison of array of JSON objects and JSON array

I am facing the problem in generic extract object fixture .
My service layer provides me Json something like this. It is an array/list of values
[{"id":1,"description":"Anti-takeover Provision"},
{"id":2,"description":"Capital Structure"},
{"id":3,"description":"Director"},
{"id":4,"description":"Equity Plan"},
{"id":5,"description":"Executive Compensation"},
{"id":6,"description":"General Governance"},
{"id":7,"description":"Merger or Acquisition"},
{"id":12,"description":"Other"},
{"id":8,"description":"Proxy Contest"},
{"id":9,"description":"Reincorporation"},
{"id":10,"description":"Shareholder Proposal"},
{"id":11,"description":"Shareholder Rights"}]
But my database json
{"document":[{"VALUE":"Anti-takeover Provision","TOPIC_ID":1},
{"VALUE":"Capital Structure","TOPIC_ID":2},
{"VALUE":"Director","TOPIC_ID":3},
{"VALUE":"Equity Plan","TOPIC_ID":4},
{"VALUE":"Executive Compensation","TOPIC_ID":5},
{"VALUE":"General Governance","TOPIC_ID":6},
{"VALUE":"Merger or Acquisition","TOPIC_ID":7},
{"VALUE":"Other","TOPIC_ID":12},
{"VALUE":"Proxy Contest","TOPIC_ID":8},
{"VALUE":"Reincorporation","TOPIC_ID":9},
{"VALUE":"Shareholder Proposal","TOPIC_ID":10},
{"VALUE":"Shareholder Rights","TOPIC_ID":11}]}
How do i compare these two values easily?
Check that the lengths are the same
Sort the two lists by their corresponding ID fields
Check that the values match
// stop as soon as you find a difference
for(i=0; i < listLength; i++) {
if (listA[i].id != listB[i].TOPIC_ID) { return false; }
if (listA[i].description != listB[i].VALUE) { return false; }
}
// if you get here, they must be the same
return true;

Avoid conflicting when "matching" users for multiplayer game

I have tried both FireBase and PubNub to create this simple multiplayer game. Created with only two players. One big(and justified) concern is conflicting users. Let me explain :
each "game" constructed with just two players(not more). If 4 players logs as the same time. And each player search for a "match". player one might match with player two.while player two might match with player three, and so on.
How can i avoid it, and guarantee that each player will get a single and unique match?, or in other words , prevent matching one user with more than other one
With Firebase, security rules and transactions would be the key to an elegant solution.
If you're willing to set up a node.js script or other server-side worker, this is fairly straightforward. Players would write to a "lobby" when they want a match. The server script would perform the matches and write back the "game room" they are going to join. The structure would be basically thus:
/games/$game_id/users/user1/<user_id>
/games/$game_id/users/user2/<user_id>
/lobby/$user_id/false (an unmatched user)
/lobby/$user_id/$game_id (a matched user)
Now clients would simply write to the lobby when they want to join a game, and then wait for the server to assign them a game id:
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby/' + <my user id>);
lobbyRef.set(false); // I want to join a game
lobbyRef.on('value', function(snap) {
if( snap.val() !== null ) {
console.log('I joined a game!', snap.val());
}
});
The server is nearly as simple. Assuming node.js:
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby');
var gamesRef = ref.child('games');
var player1 = null;
// listen for requests to join
lobbyRef.on('child_added', function(snap) {
// assign as player1 if nobody is waiting
if( !player1 ) {
player1 = snap.ref();
}
// if someone is already waiting, assign both players a room
else {
var player2 = snap.ref();
var gameRef = gamesRef.push({
players: {
player1: player1.key(),
player2: snap.key()
}
}, function(err) {
if( err ) { throw err; } // a bug
// let the players know they have been matched and which room to join
player1.set(gameRef.key());
player2.set(gameRef.key());
});
}
});
Obviously there is some work to make all this fault tolerant and security rules would be needed to prevent cheating.
Doing this entirely on the client is slightly more involved, but certainly manageable.
Have each player attempt to match themselves to anybody in the lobby. If nobody is in the lobby, then wait there. This is done with a transaction to prevent conflicts.
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby');
function waitInLobby() {
lobbyRef.once('value', lobbyUpdated);
}
function lobbyUpdated(snap) {
if( snap.val() === null ) {
// lobby is empty, so join and wait
var ref = lobbyRef.child('<my user id>').push(false);
ref.on('value', someoneMatchedMe);
function someoneMatchedMe(snap) {
if( snap.val() !== false ) {
console.log('I got matched in room', snap.val());
ref.off('value', someoneMatchedMe); // stop monitoring
snap.ref().remove(); // leave the lobby
}
}
}
else {
// lobby is not empty, so try to match someone
var possibles = [];
snap.forEach(function(ss) {
possibles.push(ss.ref());
});
}
}
function matchUser(possibles) {
if( !possibles.length ) { waitInLobby(); }
var opponentRef = lobbyRef.child(possibles.shift());
opponentRef.transaction(function(currentVal) {
if( currentVal !== false ) {
// already claimed, start over
matchUser(possibles);
}
});
}
Some security rules would be critical here, in addition to the transactions. There is also plenty of room for optimization, but at the point that you're optimizing for production, that's a job for your engineering team, rather than a Stack Overflow contributor.
matching
[p1] - [p2] - [p3] - [p4] - [p5] - etc...
Ok so you match odd numbered player (N) with the next even numbered player (N + 1).
Of course P5 stays alone and should wait for the next round, make him P1 for that round. That way he never has to wait 2 rounds
You can create a tuple for the pairs, but I would make the Player class also have a field oponent of type Player
edit1: You keep track of the raw queue in a regular array of Players. As soon as the array reaches it's desired size you trigger the above algorithm which stops the ability to change to current player pool and all matches will be definitive.
idle check
Ok so you let players enter the queue and you display a timer / empty slot counter so they have feedback how long they have to wait.
As soon as the match starts you let them lock in (League of Legends does it this way as well)
If 1 or more players do not lock in you start the queue process over, maybe with a decreased timer so the players don't have to wait to long.
If you make this time based (not slot based) then if 1 players does not respond (let's say P2) you move the last player (P5) to his slot (P5 is now P2) and everyone can play.
If you have more questions I will edit this answer.

how to disable multi-column sort in ui-grid

I have a client who specifically does not like the numbers next in the headers of the columns when doing a sort. This is rooted in UI-Grid's multi-sort, which gives each column a numbered priority. Is there a way to disable the multi-sort in order to remove those numbers? I still want to keep sorting activated, but only on one column at a time.
Thanks.
I've had this problem myself. If you look carefully in the ui0grid.js code you'll see that there is (at this time) no option to diable it. The writers of ui-grid state that they would welcome a request for such a function in this thread
However, you want a fix, not a promise ;-)
You can spot how many sortColumns have been chosen in the sortChanged method.
Try something like this:
$scope.gridOptions.onRegisterApi = function(gridApi) {
$scope.gridApi = gridApi;
// Register a handler that is fired everytime someone changd the sort params.
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length > 1) {
// We have more than one sort. Kill the first one.
// If this works we'll only ever have 0, 1 or 2 sortColumns,
// and only ever 2 for the lifetime of this method.
var column = null;
for (var j = 0; j < grid.columns.length; j++) {
if (grid.columns[j].name === sortColumns[0].field) {
column = grid.columns[j];
break;
}
}
if (column) {
sortColumns[1].sort.priority = 1; // have to do this otherwise the priority keeps going up.
column.unsort();
}
}
});
};
This is against the 3.0.0 release of ui-grid.
HTH
To prevent sorting on multiple columns, I added these two lines in the Grid.prototype.sortColumn function, ui-grid.js file.
self.resetColumnSorting(column);
column.sort.priority = undefined;
works for me..
I wanted to limit multiple sort columns to a maximum of 2. This is how I did it.
$scope.gridOptions.onRegisterApi = function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length == 3) {
//limit multi column sort to max 2 columns
for (var j = 0; j < grid.columns.length; j++) {
if (grid.columns[j].name === sortColumns[2].name) {
grid.columns[j].sort = {};
break;
}
}
return;
});
};
Looks like this is supported now in the HTML element:
[suppressMultiSort]="true"
This in the latest version. No need for tough scripts.

removeAtIndex() not working on Swift array

I have a Swift n00b question.
I'm having a hard time understanding why I cannot remove an element from an array.
I first filter it twice to contain only the values I need:
let filteredShowtimes = movieShowtimes.filter{$0.dateTime.laterDate(newStartTime!).isEqualToDate($0.dateTime)}
var furtherFilteredShowtimes = filteredShowtimes.filter{$0.endTime.earlierDate(endTime!).isEqualToDate($0.endTime)}
And, down the line, inside a while loop that depends on the size of the array - but doesn't iterate over it or modify it - I try removing the first element like so:
furtherFilteredShowtimes.removeAtIndex(0)
But the element count remains the same.
Any idea what I'm missing?
Here's the whole code:
while(furtherFilteredShowtimes.count > 0) {
println("showtime \(furtherFilteredShowtimes.first!.dateTime)")
//if the start time of the movie is after the start of the time period, and its end before
//the requested end time
if (newStartTime!.compare(furtherFilteredShowtimes.first!.dateTime) == NSComparisonResult.OrderedAscending) && (endTime!.compare(furtherFilteredShowtimes.first!.endTime) == NSComparisonResult.OrderedDescending) {
let interval = 1200 as NSTimeInterval
//if the matching screenings dict already contains one movie,
//make sure the next one starts within 20 min of the previous
//one
if(theaterMovies.count > 1 && endTime!.timeIntervalSinceDate(newStartTime!) < interval {
//add movie to the matching screenings dictionary
println("we have a match with \(movies[currentMovie.row].title)")
theaterMovies[furtherFilteredShowtimes.first!.dateTime] = movies[currentMovie.row].title
//set the new start time for after the added movie ends
newStartTime = movieShowtimes.first!.endTime
//stop looking for screenings for this movie
break
}
else if(theaterMovies.count == 0) {
//add movie to the matching screenings dictionary
theaterMovies[furtherFilteredShowtimes.first!.dateTime] = movies[currentMovie.row].title
println("we have a new itinerary with \(movies[currentMovie.row].title)")
//set the new start time for after the added movie ends
newStartTime = furtherFilteredShowtimes.first!.endTime
//stop looking for screenings for this movie
break
}
}
else { //if the showtime doesn't fit, remove it from the list
println("removing showtime \(furtherFilteredShowtimes.first!.dateTime)")
furtherFilteredShowtimes.removeAtIndex(0)
}
}
You only say removeAtIndex(0) in one place, in an else.
So if it doesn't happen, that means that line is never being executed because the else is not executed - the if is executed instead.
And you break at the end of each if, so that's the end of the while loop!
In other words, let's pretend that the first two nested if conditions succeed. Your structure is like this:
while(furtherFilteredShowtimes.count > 0) {
if (something) {
if (somethingelse) {
break
break means jump out of the while, so if those two if conditions succeed, that's the end! We never loop. We certainly will never get to the removeAtIndex().

Formatting lua table for a parse $in query that is also a table

I am using corona (lua) with parse.com and I have hit a problem constructing an $in query using values from another table / array.
My code is a little like this:
local usersToFetch = {}
table.insert( usersToFetch, "KnVvDiV2Cj")
table.insert( usersToFetch, "Paf6LDmykp")
and the working query I want to perform is the following lua table (which will get encoded before heading to parse). As I said, this works when I am hard coding the values as shown
local queryTable = {
["where"] = {
["objectId"] = { ["$in"] = {"KnVvDiV2Cj","Paf6LDmykp" }}
},
["limit"] = 1000
}
My problem is how do I incorporate my 'usersToFetch' table in the above table so that it will work the same as hard coding the values?
I swore I tried that but clearly I did not.. I think that I placed it inside the braces whereas they are not needed which is where I went wrong.
Thanks, hjpotte92 - what you put worked fine but this is my final solution in a single declaration:
Where I was going wrong before was because I had too many braces ["objectId"] = { ["$in"] = { usersToFetch } }
local queryTable = {
["where"] = {
["objectId"] = { ["$in"] = usersToFetch}
},
["limit"] = 1000
}

Resources