I'm using a turn-based match for a board game, and when a turn is complete I call GKTurnBasedMatch.EndTurn and pass the match participants and the new match data as the arguments. I need the game to advance to the unmatched players, but it only does so after some indeterminate time related to the timeout value. Setting the timeout value 0 only prevents the game from ever progressing past player 1. The match data is being updated, so the app is definitely communicating with Game Center servers. What am I missing here?
private void endTurn(double timeout)
{
// Copies list of participants to a mutable array
GKTurnBasedParticipant[] Participants = new GKTurnBasedParticipant[match.Participants.Length];
match.Participants.CopyTo(Participants, 0);
// Advances to the next player
match.EndTurn(Participants, timeout, matchData, (e) =>
{
// If there is an error message, print it to the console
if (e != null)
{
Console.WriteLine(e.LocalizedDescription);
Console.WriteLine(e.LocalizedFailureReason);
}
// Otherwise proceed normally
else
turnOverUpdate();
});
}
Apple's documentation is quite poor for the EndTurn method, but I figured it out. The NextParticipants field should be treated like EndTurnWithNextParticipant, so you have to copy GKTurnBasedMatch.Participants and reorder it so the next player is first and so fourth. The match only gives you the participants in order of joining, not relative to the local player, so you have to sort it. Below is the code I used to accomplish this.
List<GKTurnBasedParticipant> participants = new List<GKTurnBasedParticipant>();
// Gets the index of the local player
int index = 0;
for (int i = 0; i < match.Participants.Length; i++)
{
if (match.Participants[i].Player != null)
{
if (match.Participants[i].Player.PlayerID == GKLocalPlayer.LocalPlayer.PlayerID)
{
index = i;
break;
}
}
}
int offset = match.Participants.Length - index;
for (int i = 1; i < offset; i++)
participants.Add(match.Participants[i + index]);
for (int i = 0; i <= index; i++)
participants.Add(match.Participants[i]);
GKTurnBasedParticipant[] nextParticipants = participants.ToArray();
Related
I have a List of the type Model. when I loop all its elements and loop the next one except for the last one, then change the last one manually, the one before changes.
here is a little code to reproduce the problem (also you can run it directly in dartpad from here)
void main() {
List<Model> s = [];
for (int i = 0; i < 5; i++) {
s.add(Model(i));
}
for (int i = 0; i < s.length - 1; i++) {
s[i] = s[i + 1];
}
print(s);
s[s.length-1].x = 100;
print(s);
}
class Model {
int x;
Model(this.x);
#override
String toString() => 'x: ' + this.x.toString();
}
notice that this problem does not happen when you comment out the for loop or the manual change, or instead of changing the last one's property, you reassign a new value to it, like s[s.length - 1] = Model(100);. seems like dart for some reason is re-running the loop.
When you run the second for loop, you assign the i + 1th Model to the ith position in the list:
// initialise list
for (int i = 0; i < s.length; i++) {
s[i] = s[i + 1]
}
If you unwrap the loop, it looks roughly like this:
s[0] = s[1];
s[1] = s[2];
s[2] = s[3];
s[3] = s[4];
Notice that this leaves s[4] unchanged, but also assigns it to s[3].
In Dart, variables contain references to objects. This means that when your list runs s[3] = s[4];, both s[3] and s[4] point to the same object.
Now, if you modify s[4] you, are actually modifying the objects that s[4] refers to, which happens to also be the object that s[3] refers to, so they both appear to change in your list.
Is there any way to generate random numbers without duplication?
For instance I want to generate 50 random numbers from 1 to 100 no duplication, any way to do this or do I have to check every time incoming number is already created or not?
you can use shuffle as following code.
import 'dart:math';
var list = new List<int>.generate(10, (int index) => index); // [0, 1, 4]
list.shuffle();
print(list);
You can use Set. Each object can occur only once when using it. Just try this:
Set<int> setOfInts = Set();
while (setOfInts.length < 50) {
setOfInts.add(Random().nextInt(range) + 1);
}
You can read the documentation here: Set Doc
Here is an alternative that avoids creating an array of all the possible values, and avoids repeatedly looping until no collision occurs. It may be useful when there is a large range to select from.
import 'dart:math';
class RandomList {
static final _random = new Random();
static List<int> uniqueSample({int limit, int n}) {
final List<int> sortedResult = [];
final List<int> result = [];
for (int i = 0; i < n; i++) {
int rn = _random.nextInt(limit - i); // We select from a smaller list of available numbers each time
// Increment the number so that it picks from the remaining list of available numbers
int j = 0;
for (; j < sortedResult.length && sortedResult[j] <= rn; j++) rn++;
sortedResult.insert(j, rn);
result.add(rn);
}
return result;
}
}
I haven't tested it exhaustively but it seems to work.
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.
I am trying to find the middle element of a double linked list in constant time complexity .
I came across the following http://www.geeksforgeeks.org/design-a-stack-with-find-middle-operation/ solution.
But I don't understand how to use the middle pointer.
Can anyone please help me understand this or give me a better solution .
I've re-written this code in C++ for explanation purposes:
#include <iostream>
typedef class Node* PNode;
class Node{
public:
PNode next;
PNode prev;
int data;
Node(){
next = nullptr;
prev = nullptr;
data = 0;
}
};
class List{
private:
//Attributes
PNode head;
PNode mid;
int count;
//Methods
void UpdateMiddle( bool _add );
public:
//Constructors
List(){
head = nullptr;
mid = nullptr;
count = 0;
}
~List(){
while( head != nullptr ){
this->delmiddle();
std::cout << count << std::endl;
}
}
//Methods
void push( int _data );
void pop();
int findmiddle();
void delmiddle();
};
void List::UpdateMiddle( bool _add ){
if( count == 0 ){
mid = nullptr;
}
else if( count == 1 ){
mid = head;
}
else{
int remainder = count%2;
if(_add){
if( remainder == 0 ){
mid = mid->prev;
}
}
else{
if( remainder == 1 ){
mid = mid->next;
}
}
}
}
void List::push( int _data ){
PNode new_node = new Node();
new_node->data = _data;
new_node->prev = nullptr;
new_node->next = head;
if( head != nullptr ) head->prev = new_node;
head = new_node;
count++;
UpdateMiddle( true );
}
void List::pop(){
if( head != nullptr ){
PNode del_node = head;
head = head->next;
if( head != nullptr ) head->prev = nullptr;
delete del_node;
count--;
UpdateMiddle(false);
}
else if( count != 0 ){
std::cout << "ERROR";
return;
}
}
int List::findmiddle(){
if( count > 0 ) return mid->data;
else return -1;
}
void List::delmiddle(){
if( mid != nullptr ){
if( count == 1 || count == 2){
this->pop();
}
else{
PNode del_mid = mid;
int remainder = count%2;
if( remainder == 0 ){
mid = del_mid->next;
mid->prev = del_mid->prev;
del_mid->prev->next = mid;
delete del_mid;
count--;
}
else{
mid = del_mid->prev;
mid->next = del_mid->next;
del_mid->next->prev = mid;
delete del_mid;
count--;
}
}
}
}
The push and pop functions are self-explanatory, they add nodes on top of the stack and delete the node on the top. In this code, the function UpdateMiddle is in charge of managing the mid pointer whenever a node is added or deleted. Its parameter _add tells it whether a node has been added or deleted. This info is important when there is more than two nodes.
Note that when the UpdateMiddle is called within push or pop, the counter has already been increased or decreased respectively. Let's start with the base case, where there is 0 nodes. mid will simply be a nullptr. When there is one node, mid will be that one node.
Now let's take the list of numbers "5,4,3,2,1". Currently the mid is 3 and count, the amount of nodes, is 5 an odd number. Let's add a 6. It will now be "6,5,4,3,2,1" and count will now be 6 an even number. The mid should also now be 4, as it is the first in the middle, but it still hasn't updated. However, now if we add 7 it will be "7,6,5,4,3,2,1", the count will be 7, an odd number, but notice that the mid wont change, it should still be 4.
A pattern can be observed from this. When adding a node, and count changes from even to odd, the mid stays the same, but from odd to even mid changes position. More specifically, it moves one position to the left. That is basically what UpdateMiddle does. By checking whether count is currently odd or even after adding or deleting a node, it decides if mid should be repositioned or not. It is also important to tell whether a node is added or deleted because the logic works in reverse to adding when deleting. This is basically the logic that is being applied in the code you linked.
This algorith works because the position of mid should be correct at all times before adding or deleting, and function UpdateMiddle assumes that the only changes were the addition or deletion of a node, and that prior to this addition or deletion the position of mid was correct. However, we make sure of this by making the attributes and our function UpdateMiddle private, and making it modifiable through the public functions.
The trick is that you don't find it via a search, rather you constantly maintain it as a property of the list. In your link, they define a structure that contains the head node, the middle node, and the number of nodes; since the middle node is a property of the structure, you can return it by simply accessing it directly at any time. From there, the trick is to maintain it: so the push and pop functions have to adjust the middle node, which is also shown in the code.
More depth: maintaining the middle node: we know given the count that for an odd number of nodes (say 9), the middle node is "number of nodes divided by 2 rounded up," so 9/2 = 4.5 rounded up = the 5th node. So if you start with a list of 8 nodes, and add a node, the new count is 9, and you'll need to shift the middle node to the "next" node. That is what they are doing when they check if the new count is even.
I need help with seeding data in a league with 12 teams, each team has a TeamId key value of 1 to 12 respectively
I have pre-populated and seeded the ScheduledFixtures table with 22 rows. In my attempt below I do a take 11 while i try to set up the first half of season, i.e. everyone plays everyone once. Each week for each team has to be home game, then away game
My code is at a point where it works in that it seeds the right number of rows but the wrong teamId's are set in fixture game. This is the bit I cannot figure out. So ScheduleFixture 1 loops once and I need each team to play each other, then next loop same again but who was at home is now away etc etc
var sheduledFixtures = db.ScheduledFixtures.Take(22);
var teams = db.Teams;
foreach (var x in sheduledFixtures)
{
var i = 1;
for (int t = 1; t < 8; t++)
{
if (t != i)
{
var fixtureGame = new FixtureGame();
fixtureGame.AwayTeamId = i;
fixtureGame.HomeTeamId = t;
db.FixtureGames.Add(fixtureGame);
db.SaveChanges();
// Add Fixture Record
var fixture = new Fixture();
fixture.FixtureGameId = fixtureGame.FixtureGameId;
fixture.SeasonId = 1;
fixture.ScheduledFixtureId = x.ScheduledFixtureId;
db.Fixtures.Add(fixture);
i++;
}
}
}
db.SaveChanges();