IBeacon. Custom filter regions - ibeacon

Good day. Sorry my English is bad. Whether prompt there is an opportunity to define region of bicons not on UUID and on it is one part. For example, we have 2 regions:
1 - UUID = 57547265-7261-772e-636f-6c0054000000
2- there is only the full part (most likely this is the fourth last group) -
6c001137e000
Can I just specify in my method a filter only for the last group of UUID?
For example:
List<string> listUuids =new List<string>()
{ "57547265-7261-772e-636f-6c0054000000" , "6c001137e000" };
for (int i = 0; i <listUuids.Count; i ++)
{
var uuid = Identifier.Parse (listUuids [i]);
var region = new Region ("R" + i, uuid, null, null);
beaconManager.StartRangingBeaconsInRegion (region);
}
I would really appreciate any answers!
Best Regards!

You can do this with a custom beacon parser. Like this:
BeaconManager.GetBeaconParsers().clear();
BeaconMannager.GetBeaconParsers().add(new Beacon parser().setBeaconLayout("m:2-3=0215,i:14-19,i:4-13,i:20-21,i:22-23,p:24-24");
var region = new Region("partial UUID region", Identifier.parse("0x6c001137e000"), null, null)
The above custom parser defines four identifiers for a iBeacon packet. The first identifier is the last 6 bytes of the UUID. The second identifier is the first 10 bytes of the UUID. The third and fourth identifiers are the major and minor, respectively.
Using the region defined above will match any beacon matching the specified last 6 bytes of the UUID.

Related

Powerquery - Algorithm required for this task

Long time lurker, first time poster. Apologies in advance if my question appears a bit noobish.
I am new to powerquery/powerbi and trying to develop a report to solve a small logistics issue we are facing.
I have a list of cables that are given to our technicians to use of different pre-terminated lengths which they will use for their application. Ideally the closest length cable to the length of the route should be utilized, however that is not always the case. I want to match the cables issued to the routes (Column "Actual Cables Utilised"). Example below:
Cables issued:
Breakdown:
Highlighted in green are the accepted substitutions. Red is the wrong substitution (There isn't a cable issued that is longer than the route).
I cannot find a way to run a loop in powerquery that would populate the breakdown table based on the issued table. Please note that unfortunately, my company does not allow python or r-script on our computers, so I am limited to basic power query.
Any assistance would be greatly appreciated!
This might work
Group the Breakdown table by technician
For each technician, generate a list of Issued cables with an entry for each cable (i.e. if there are 2 - 40m cables, 40 will appear twice in the list.
The Issued cables will be assigned sequentially in the order presented by the Breakdown sheet.
Use a recursive function that, as it generates the Utilized cable list, removes that entry from the Issued cables.
Main Code
let
//Read in the Issued and Breakdown tables
//Change the Source lines to reflect your own data sources for these tables
Source1 = Excel.CurrentWorkbook(){[Name="Issued"]}[Content],
Issued = Table.TransformColumnTypes(Source1, List.Transform(Table.ColumnNames(Source1), each {_, Int64.Type})),
Source = Excel.CurrentWorkbook(){[Name="Breakdown"]}[Content],
Breakdown = Table.TransformColumnTypes(Source,{
{"Technician", type text}, {"Route Length (m)", Int64.Type}, {"Ideal Cable Length (m)", Int64.Type}}),
//Group by Technician
// Generate a list of cables where there is one entry for every issued cable
// Then call the custom (recursive) function to generate an appropriate list for each tech
#"Grouped Rows" = Table.Group(Breakdown, {"Technician"}, {
{"Cables", (t)=>
let
cables = List.Combine(
List.Generate(
()=> [c=List.Repeat({Issued[Cable Lengths]{0}}, Table.Column(Issued, t[Technician]{0}){0}), idx=0],
each [idx] < Table.RowCount(Issued),
each [c=List.Repeat({Issued[Cable Lengths]{[idx]+1}}, Table.Column(Issued, t[Technician]{0}){[idx]+1}), idx = [idx]+1],
each [c])),
x = fnBreakdown(t, cables)
in
x, type list}}),
#"Expanded Cables" = Table.ExpandListColumn(#"Grouped Rows", "Cables"),
//add the utilized cable column back to the Breakdown table
#"Breakdown Table" = Table.FromColumns(
Table.ToColumns(Breakdown) & {#"Expanded Cables"[Cables]},
type table[Technician=text, #"Route Length (m)"=Int64.Type,
#"Ideal Cable Length (m)"=Int64.Type,Actual Cable Utilized=Int64.Type]
)
in
#"Breakdown Table"
Custom Function rename fnBreakdown
//Rename this query "fnBreakdown"
//tech = the subtable all with the same technician
//cables = a list of cables with a single entry for each size
// generated by List.Repeat in the original call from the main code
//cableList = a list of the utilized cable
//Index is the index into the Tech table
(tech as table, cables as list, optional cableList as list, optional Index as number)=>
let
//set intial values for optional arguments
idx = if Index = null then 0 else Index + 1,
cableL = if cableList = null then {} else cableList,
//determine cable matching for "idx"th entry
//if there is no match then write a null
#"New Cab" = List.Select(cables, each _ >= tech[#"Route Length (m)"]{idx}),
#"New Cable" = if #"New Cab" = {} then null else #"New Cab"{0},
//Remove the used cable from the list of "cables"
#"New Cables" = if List.PositionOf(cables,#"New Cable",Occurrence.First) = -1
then cables
else List.RemoveRange(cables,List.PositionOf(cables,#"New Cable",Occurrence.First),1),
//new cable list for this tech
#"New Cable List" = cableL & {#"New Cable"},
//if we haven't checked all the routes then recursively call the function with the updated arguments
result = if idx < Table.RowCount(tech)-1
then fnBreakdown(tech,#"New Cables", #"New Cable List", idx)
else #"New Cable List"
in
result
Results from your data above

Get separate data from Firebase in Swift

I can't get data and write to String variable.
When I do:
myRootRef.observeEventType(.ChildAdded, withBlock: {
snapshot in
print(snapshot.value.objectForKey("02-03-2016"))
})
I get all this records (in type - AnyObject):
Optional({
TD = {
Entry = 44;
Name = Tedd;
Potential = 32;
StopLoss = 77;
};
})
But I need "Entry", "Name", "Potential", "StopLoss" - put to variables, and after put to textfield...
Help please to understand, how I can do it.
I can't find solution already more 4 hours....
Thanks.
You are trying to print a value associated with a key. ( a key:value pair)
The key you are specifying is "02-03-2016" and that key doesn't seem to exist.
Assuming your structure is
Entry = 44;
Name = Tedd;
Potential = 32;
StopLoss = 77;
Then your keys are Entry, Name, Potential and StopLoss
print(snapshot.value.objectForKey("Entry")
would print
44

Firebase: How to match opponents in a game?

I'm implementing a social chess game. Every user can create a new game, and they'll wait until the system will find an opponent for them.
When user creates a game, they specify constraints: color they'd like to play, and opponent's minimal chess rating.
Opponents can either match or not match. For example, the following two opponents will match:
// User 1 with rating 1700 // User 2 with rating 1800
// creates this game // creates this game
game: { game: {
color: 'white', minRating: 1650
minRating: 1600 }
} // User did not specify a preferred color,
// meaning they do not care which color to play
So, if User 1 is the first user in the system, and created their game, they'll wait. Once User 2 creates their game, they should be matched immediately with User 1.
On the other side, the following two opponents won't match, because they both want to play white. In this case, both should wait until someone else creates a game with color: 'black' (or color not specified), and minRating that would match the requirements.
// User 1 with rating 1700 // User 2 with rating 1800
// creates this game // creates this game
game: { game: {
color: 'white', color: 'white'
minRating: 1600 minRating: 1650
} }
My concerns related to scenarios where thousands of users creates new games at the same time. How do I make sure that I match opponents without creating deadlocks? i.e. how do I prevent scenarios when User 1, User 2, and User 3 are trying to find an opponent at the same time, and their matching algorithms return User 99. How do I recover from this scenario, assigning User 99 to only one of them?
How would you use the power of Firebase to implement such a matching system?
The obvious choice for a starting point would be the color, since this is an exclusive requirement. The others seem more like weighted results, so those could simply increment or decrement the weight.
Utilize priorities for min/max ranges, and keep each in a separate "index". Then grab the matches for each and create a union. Consider this structure:
/matches
/matches/colors/white/$user_id
/matches/ranking/$user_id (with a priority equal to ranking)
/matches/timezones/$user_id (with a priority of the GMT relationship)
Now to query, I would simply grab the matches in each category and rank them by the number of matches. I can start with colors, because this presumably isn't an optional or relative rating:
var rootRef = new Firebase('.../matches');
var VALUE = {
"rank": 10, "timezone": 5, "color": 0
}
var matches = []; // a list of ids sorted by weight
var weights = {}; // an index of ids to weights
var colorRef = rootRef.child('colors/black');
colorRef.on('child_added', addMatch);
colorRef.child('colors/black').on('child_removed', removeMatch);
var rankRef = rootRef.child('ranking').startAt(minRank).endAt(maxRank);
rankRef.on('child_added', addWeight.bind(null, VALUE['rank']));
rankRef.on('child_removed', removeWeight.bind(null, VALUE['rank']));
var tzRef = ref.child('timezone').startAt(minTz).endAt(maxTz);
tzRef.on('child_added', addWeight.bind(null, VALUE['timezone']));
tzRef.on('child_removed', removeWeight.bind(null, VALUE['timezone']));
function addMatch(snap) {
var key = snap.name();
weights[key] = VALUE['color'];
matches.push(key);
matches.sort(sortcmp);
}
function removeMatch(snap) {
var key = snap.name();
var i = matches.indexOf(key);
if( i > -1 ) { matches.splice(i, 1); }
delete weights[key];
}
function addWeight(amt, snap) {
var key = snap.name();
if( weights.hasOwnProperty(key) ) {
weights[key] += amt;
matches.sort(sortcmp);
}
}
function removeWeight(amt, snap) {
var key = snap.name();
if( weights.hasOwnProperty(key) ) {
weights[key] -= amt;
matches.sort(sortcmp);
}
}
function sortcmp(a,b) {
var x = weights[a];
var y = weights[b];
if( x === y ) { return 0; }
return x > y? 1 : -1;
}
Okay, now I've given what everyone asks for in this use case--how to create a rudimentary where clause. However, the appropriate answer here is that searches should be performed by a search engine. This is no simple where condition. This is a weighted search for the best matches, because fields like color are not optional or simply the best match, while others--ranking maybe--are the closest match in either direction, while some simply affect the quality of the match.
Check out flashlight for a simple ElasticSearch integration. With this approach, you should be able to take advantage of ES's great weighting tools, dynamic sorting, and everything else you need to conduct a proper matching algorithm.
Regarding deadlocks. I would not put too much focus here until you have hundreds of transactions per second (i.e. hundreds of thousands of users competing for matches). Split out the path where we will write to accept a join and do a transaction to ensure only one person succeeds in obtaining it. Keep it separate from the read data so that the lock on that path won't slow down processing. Keep the transaction to a minimal size (a single field if possible).
It is a challenging task in NoSQL environment especially if you want to match multiple fields
in your case, I would setup a simple index by color and within the color I would store the reference to the game with priority set to minRating.
That way you can query the games by the prefered colour with the priority of minRating.
indexes: {
color:{
white:{
REF_WITH_PRIORITY_TO_RATING: true
},
black:{
REF_WITH_PRIORITY_TO_RATING: true
}
}
}
if you want to get info whenever the match opens the game:
ref = new(Firebase)('URL');
query =ref.child('color_index/white/').startAt(minPriority);
query.on('child_added',function(snapshot){
//here is your new game matching the filter
});
This, however, it would get more complex if you introduce multiple fields for filtering the games for example dropRate, timeZone, 'gamesPlayed' etc... In this case, you can nest the indexes deeper:
indexes: {
GMT0: {
color:{
white:{
REF_WITH_PRIORITY_TO_RATING: true
},
black:{
REF_WITH_PRIORITY_TO_RATING: true
},
}
GMT1: {
// etc
}
}

Data comparing in dataset

I had to write a method that does the following:
There is a DataSet let's say CarDataSet with one table Car and contains Primary key Id and one more column ColorId. And there is a string with Ids seperated with commas for example "5,6,7,8" (random length). The task is to check if all appropriate ColorIds are identical for given Car Ids.
For example:
String ids = "5,6,7,8"
If all the Cars ColorIds are for example 3,3,3,3 where the Car Ids are 5,6,7,8 then return true;
In other words - check if all cars with given Ids are in one color. Now I don't have my code anymore but I made this using 3 foreach loops and 3 linq expressions. Is there any simplier way to do this?
If you want all cars have same color means all of them should have same color as first one:
// first find the cars with given ids
var selectedCars = Cars.Where(x=>ids.Contains(x.ID.ToString());
// select one of them as comparer:
var firstCar = selectedCars.FirstOrDefault();
if (firstCar == null)
return true;
// check all of them has same color as first one:
return selectedCars.All(x=>x.ColorID == firstCar.ColorID);
Edit: Or if you have no problem with throwing exception when there is no car with given ids you can use two query in lambda syntax:
var selectedCars = Cars.Where(x=>ids.Contains(x.ID.ToString()));
return selectedCars.All(x=>x.ColorID == selectedCars.First().ColorID);
You could do this by performing a distinct, and asserting the count is 1.
var colors = Cars.Where(x=>ids.Contains(x.ID.ToString())
.Select(x=>x.ColorID)
.Distinct().Count();
return count == 1;

At least one one object must implement Icomparable

I am attempting to get unique values in a list of similar value distinguished only by a one element in a pipe delimited string... I keep getting at least one object must implement Icomparable. I don't understand why I keep getting that. I am able to groupBy that value... Why can't I find the max... I guess it is looking for something to compare it with. If I get the integer version will it stop yelling at me? This is the last time I am going to try using LINQ...
var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1]).Select(x => x.Max());
I know I can get the unique values some other way. I am just having a hard time figuring it out. In that List I know that the string with the highest value amongst its similar brethren is the one that I want to add to the list. How can I do that? I am totally drawing a blank because I have been trying to get this to work in linq for the last few days with no luck...
foreach (XmlNode node in nodeList)
{
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(node.OuterXml);
string popPatInfo = xDoc.SelectSingleNode("./template/elements/element[#name=\"FirstName\"]").Attributes["value"].Value + ", " + xDoc.SelectSingleNode("./template/elements/element[#name=\"LastName\"]").Attributes["value"].Value + " | " + DateTime.Parse(xDoc.SelectSingleNode("./template/elements/element[#name=\"DateOfBirth\"]").Attributes["value"].Value.Split('T')[0]).ToString("dd-MMM-yyyy");
string patientInfo = xDoc.SelectSingleNode("./template/elements/element[#name=\"PatientId\"]").Attributes["value"].Value + "|" + xDoc.SelectSingleNode("./template/elements/element[#name=\"PopulationPatientID\"]").Attributes["enc"].Value;// +"|" + xDoc.SelectSingleNode("./template/elements/element[#name=\"AdminDate\"]").Attributes["value"].Value;
int enc = Int32.Parse(patientInfo.Split('|')[1]);
if (enc > temp)
{
lastEncounter.Add(enc, patientInfo);
temp = enc;
}
//lastEncounter.Add(Int32.Parse(patientInfo.Split('|')[1]));
PatientList.Add( new SelectListItem { Text = popPatInfo, Value = patientInfo });
}
I was thinking about using some kind of temp variable to find out what is the highest value and then add that string to the List. I am totally drawing a blank however...
Here I get the IDs in an anonymous type to make it readable.
var patientEncounters= from patient in PatientList
let PatientID=Int32.Parse(patient.Value.Split('|')[0])
let EncounterID=Int32.Parse(patient.Value.Split('|')[1])
select new { PatientID, EncounterID };
Then we group by UserID and get the last encounter
var lastEncounterForEachUser=from pe in patientEncounters
group pe by pe.PatientID into grouped
select new
{
PatientID=grouped.Key,
LastEncounterID=grouped.Max(g=>g.EncounterID)
};
Linq doesn't know how to compare 2 Patient objects, so it can't determine which one is the "greatest". You need to make the Patient class implement IComparable<Patient>, to define how Patient objects are compared.
// Compare objets by Id value
public int CompareTo(Patient other)
{
return this.Id.CompareTo(other.Id);
}
Another option is to use the MaxBy extension method available in Jon Skeet's MoreLinq project:
var queryResults = PatientList.GroupBy(x => x.Value.Split('|')[1])
.Select(x => x.MaxBy(p => p.Id));
EDIT: I assumed there was a Patient class, but reading your code again, I realize it's not the case. PatientList is actually a collection of SelectListItem, so you need to implement IComparable in that class.

Resources