How to get nearby locations from latitude/longitude? - iphone

I have store various latitude and longitude in database(Sqlite3) for various location. Now I have current latitude and longitude. How can I know nearest locations from current position.
Please suggest.

I assume you're talking about Reverse Geocoding. There's an Apple class provided for that, MKReverseGeocoder. There are also plenty of how-to discussions about that, such as here, here, etc.

The syntax will likely need to change, but take a look at this question that uses MySQL. Essentially you want to create a rectangle with the current point at the center (most likely). Using the bounds of this new box, you can run your SQL query.

I dare say #Kongress answer is the best here - but I'm just going to chuck this one into the ring as the concept itself is one that I've dealt with before.
I can't tell you how to build one in objective-c, but for our lat/long reverse lookup I built a K-DTree from the lat longs in our database ( > 250,000) and it gives us sub-100-nanosecond lookups on desktop hardware. On an iphone it's still likely to be pretty fast - memory might be a concern though as you really need to be able to cache the instance in memory, to be really useful; it takes a little while to build it (ours builds in about 1.5 seconds).
Just an idea.

Related

Firebase analytics - Unity - time spent on a level

is there any possibility to get exact time spent on a certain level in a game via firebase analytics? Thank you so much 🙏
I tried to use logEvents.
The best way to do so would be measuring the time on the level within your codebase, then have a very dedicated event for level completion, in which you would pass the time spent on the level.
Let's get to details. I will use Kotlin as an example, but it should be obvious what I'm doing here and you can see more language examples here.
firebaseAnalytics.setUserProperty("user_id", userId)
firebaseAnalytics.logEvent("level_completed") {
param("name", levelName)
param("difficulty", difficulty)
param("subscription_status", subscriptionStatus)
param("minutes", minutesSpentOnLevel)
param("score", score)
}
Now see how I have a bunch of parameters with the event? These parameters are important since they will allow you to conduct a more thorough and robust analysis later on, answer more questions. Like, Hey, what is the most difficult level? Do people still have troubles on it when the game difficulty is lower? How many times has this level been rage-quit or lost (for that you'd likely need a level_started event). What about our paid players, are they having similar troubles on this level as well? How many people have ragequit the game on this level and never played again? That would likely be easier answer with sql at this point, taking the latest value of the level name for the level_started, grouped by the user_id. Or, you could also have levelName as a UserProperty as well as the EventProperty, then it would be somewhat trivial to answer in the default analytics interface.
Note that you're limited in the number of event parameters you can send per event. The total number of unique parameter names is limited too. As well as the number of unique event names you're allowed to have. In our case, the event name would be level_completed. See the limits here.
Because of those limitations, it's important to name your event properties in somewhat generic way so that you would be able to efficiently reuse them elsewhere. For this reason, I named minutes and not something like minutes_spent_on_the_level. You could then reuse this property to send the minutes the player spent actively playing, minutes the player spent idling, minutes the player spent on any info page, minutes they spent choosing their upgrades, etc. Same idea about having name property rather than level_name. Could as well be id.
You need to carefully and thoughtfully stuff your event with event properties. I normally have a wrapper around the firebase sdk, in which I would enrich events with dimensions that I always want to be there, like the user_id or subscription_status to not have to add them manually every time I send an event. I also usually have some more adequate logging there Firebase Analytics default logging is completely awful. I also have some sanitizing there, lowercasing all values unless I'm passing something case-sensitive like base64 values, making sure I don't have double spaces (so replacing \s+ with " " (space)), maybe also adding the user's local timestamp as another parameter. The latter is very helpful to indicate time-cheating users, especially if your game is an idler.
Good. We're halfway there :) Bear with me.
Now You need to go to firebase and register your eps (event parameters) into cds (custom dimensions and metrics). If you don't register your eps, they won't be counted towards the global cd limit count (it's about 50 custom dimensions and 50 custom metrics). You register the cds in the Custom Definitions section of FB.
Now you need to know whether this is a dimension or a metric, as well as the scope of your dimension. It's much easier than it sounds. The rule of thumb is: if you want to be able to run mathematical aggregation functions on your dimension, then it's a metric. Otherwise - it's a dimension. So:
firebaseAnalytics.setUserProperty("user_id", userId) <-- dimension
param("name", levelName) <-- dimension
param("difficulty", difficulty) <-- dimension (or can be a metric, depends)
param("subscription_status", subscriptionStatus) <-- dimension (can be a metric too, but even less likely)
param("minutes", minutesSpentOnLevel) <-- metric
param("score", score) <-- metric
Now another important thing to understand is the scope. Because Firebase and GA4 are still, essentially just in Beta being actively worked on, you only have user or hit scope for the dimensions and only hit for the metrics. The scope basically just indicates how the value persists. In my example, we only need the user_id as a user-scoped cd. Because user_id is the user-level dimension, it is set separately form the logEvent function. Although I suspect you can do it there too. Haven't tried tho.
Now, we're almost there.
Finally, you don't want to use Firebase to look at your data. It's horrible at data presentation. It's good at debugging though. Cuz that's what it was intended for initially. Because of how horrible it is, it's always advised to link it to GA4. Now GA4 will allow you to look at the Firebase values much more efficiently. Note that you will likely need to re-register your custom dimensions from Firebase in GA4. Because GA4 is capable of getting multiple data streams, of which firebase would be just one data source. But GA4's CDs limits are very close to Firebase's. Ok, let's be frank. GA4's data model is almost exactly copied from that of Firebase's. But GA4 has a much better analytics capabilities.
Good, you've moved to GA4. Now, GA4 is a very raw not-officially-beta product as well as Firebase Analytics. Because of that, it's advised to first change your data retention to 12 months and only use the explorer for analysis, pretty much ignoring the pre-generated reports. They are just not very reliable at this point.
Finally, you may find it easier to just use SQL to get your analysis done. For that, you can easily copy your data from GA4 to a sandbox instance of BQ. It's very easy to do.This is the best, most reliable known method of using GA4 at this moment. I mean, advanced analysts do the export into BQ, then ETL the data from BQ into a proper storage like Snowflake or even s3, or Aurora, or whatever you prefer and then on top of that, use a proper BI tool like Looker, PowerBI, Tableau, etc. A lot of people just stay in BQ though, it's fine. Lots of BI tools have BQ connectors, it's just BQ gets expensive quickly if you do a lot of analysis.
Whew, I hope you'll enjoy analyzing your game's data. Data-driven decisions rock in games. Well... They rock everywhere, to be honest.

Mapbox: Is there a way to retrieve all coordinates for a specific feature ID?

I'm building a feature where I need to extract all coordinates of a selecetd road/path in Mapbox when it's clicked on. I've attempted to use the queryRenderedFeatures method, but it seems the result list is fragmented. By "fragmented" I mean that if you have a road or path which is clearly just one long path/road when rendered on the map, it often consists up of 4-5-6 or more features, and you cannot really work out from the feature collection how they're supposed to be connected (in order)
I then tried to use the Tilequery API, but it doesn't return any coordinates for LineStrings.
Is there any API - server or client side - in Mapbox, where you can provide an ID of a feature and retrieve the all coordinates for a road or path?
Thanks in advance :-)
I think you're really asking: "is there a way to access complete LineString features for data in Mapbox's tilesets", to which the answer is, no, not really - other than trying to reassemble them in the way you have tried.
For your own data, you could host it using Mapbox's Datasets, rather than Tilesets.

How to plot a JSON file generated by osrm for route optimization into an OSM map

I am a complete newbie to computation of gps, gis and all these geoinformatical stuff. First I describe my lessons learned to arrive at gps data. You can skip this and go to the last two paragraphs where I explain my problem with osrm and how to map a route onto an OSM map via qgis or similar tools.
I tried to do some route optimization for a bunch of addresses to support my son's paper deliverer job. I was able to generate a list of gps data by using the Nomatim engine that is available via geopy.geocoders. It's kind of a Travelling Salesman problem (TSP).
By using geopy's distance calculator and the or-tools from Google to Generate a shortest list recommendation. That worked well but it was only a TSP solution for air line :-(.
Then I was looking for route optimization toolkits but i struggled to get one for free. I thought osrm could be the right tool. I followed the descriptions given at Github, see here. I was able to generate a JSON file - at least I supposed that it's kind of a JSON file. But I was unable to project this back onto a map in QGis or any online tool from OSM. Can anyone help me?
The file with such JSON-like formatting:
{"code":"Ok","waypoints":[{"hint":"Jh4BgEUzI4BhAAAACwAAAKIAAABZAAAAkLAjQgpyikBay4dCWsuHQmEAAAALAAAAogAAAFkAAAArAAAAxwB4AARI3AI3AXgAWEbcAgIADwXVhXd1","location":...
Due to privacy issues I cannot post it here with any locations. Sorry for this. But does anyone have kind of a recipe / step-by-step guide what I need to do to plot it? I even have no idea how to "open" a map within qgis. You need to do this as kind of a database but this is totally new for me. I would prefer to work with an easier method to plot it.
Thanks in advance for any help.
Please follow the API documentation here. From that documentation
hint Unique internal identifier of the segment (ephemeral, not
constant over data updates) This can be used on subsequent request to
significantly speed up the query and to connect multiple services.
E.g. you can use the hint value obtained by the nearest query as hint
values for route inputs.
You can get the geometry in many ways. Widely GeoJSON is being used by developers. OSRM returns a very clean GeoJSON which can easily be used with Leaflet, Mapbox or other Map APIs. You need to send steps parameter true to get the full step by step direction. You can get the each segments of steps in legs. So call the GeoJSON within the geometries of every legs with loop. You can also get the geometry without passing the steps parameter true. For that you will get full geometry in a single GeoJSON within the routes property.

How can I capture metrics from an emulated (SNES) game?

My goal is to emulate a game (e.g., Super Bombliss) using an Android emulator (e.g., Snes9x EX+) and to capture game metrics (e.g., score and level) as the game is played.
I assume I would need to modify the open-source emulator and/or to modify the ROM to do this, but I need some guidance on the best approach. Thanks!
To answer "How can I capture metrics from an emulated (SNES) game?" you need to first answer "Where can I find metrics in a SNES game?". The answer to the latter is "It depends on the game."
Think about GameShark codes, they write a value to a specific position of the memory.
It can write a value constantly to a memory position. For keeping you life bar always full on Mortal Kombat, for example.
It can write a value to a memory position just once. If you want to jump to last level of Sunset Riders.
But how do they know which memory position they should write to? That is the hard question. Usually it comes down to reverse engineering the ROM. You create a map of which memory position corresponds to each metric you are looking for.
Let's assume you want to find your current score and your current level on Super Mario World. A possible solution would be to constantly scan the RAM memory, looking for a known value and create a map of matches.
Knowing your score is 321, you can dump the RAM and look for where memory positions that contain 321. If only one matches, there is a very likely chance that it is the memory position that indicates your score. If you have more matches you should keep a list of all matches and keep playing until your score changes. If it changes to 567 now you check from your previous list if any of the memory positions now holds the value 567.
It is not always straight forward, for example, for the stage level 6-3. Should you look in the memory for 6 and for a 3 separately? What if the game stores the levels in just one variable represented as BCD 63. Then you would have to look for something completely different.
The only way to be sure 100% is by reverse engineering the ROM, in that way you know where the game goes fetch whatever is displayed on the screen.
Now to answer your original question "How can I capture metrics from an emulated (SNES) game?" you have to first figure out where those metrics are located in every game ROM and once you know you just need to build an emulator that listens to modifications in those memory positions so you can capture those metrics.
You can find many websites that are dedicated to reverse engineering ROMs. I suggest you take a look at the work done on http://www.romhacking.net/.

Caching Strategy for location requests

I am building REST APIs that return data (lets say events ) in particular area. The REST URL is a simple GET
/api/v1/events?lat=<lat>&lng=<lng>&radius=<radius>.
with parameters lat, lng and radius (10 miles by default), the latitude and longitude are what the device or browser APIs return. Now needless to say that the lat and lng change continuously as the user moves and also two users can be same vicinity with different lat / lng. What is the best way to cache such kind of requests on the server so that I don't have to dip into business logic everytime. The URL is not going to unique since lat/lng change.
Thanks
I'm assuming you have some sort of "grid", and when a user requests a specific coordinate, you return the grid tile(s) around the location. So you have an infinite URL space (coordinates) that is mapped to a finite number of tiles. One solution is to redirect every request to the "canonical", cache friendly URL for that tile, e.g.
GET /api/v1/events?lat=123&lng=456
=>
302 Found
Location: /api/v1/events?tile=abc
Or, if you want to retain the lat/long info in the URL, you could use the location of the center of the tile.
I think the best approach is for you to store the results in a cache with the center coordinates as a key, and later query the points within the circle for the new request.
I'm not aware of any cache engines that would allow you to perform spatial queries, so I think you'll have to use a database that allows easy querying and indexing of spatial data. You may use that database for caching your results, or at least store a key to that result in a cache engine somewhere else, and later you can query them with spatial coordinates, asking for all points with a threshold distance to your new request.
There's PostGis for PostgreSQL, which should be quite straightforward since it has full support for latitude/longitude distance computations. Once you have it setup with proper indexes, it should be as easy as:
SELECT * FROM your_cache_table
WHERE ST_Distance_Sphere(the_geom, ST_MakePoint(new_lon, new_lat)) <= 160.934
MySQL has some support for the OpenGis extensions, however it doesn't have support for latitude/longitude distance computations. Maybe you'll need to do some calculations by yourself, maybe the simple cartesian distance works for you. Check the documentation here, and this answer should also help.
I also believe even MySQL 5.6 still has support for spatial indexes only in MyISAM tables, but that shouldn't be an issue since you're using them only for cache.
Managing the cache may be a little more complicated than usual. If you need expiration, you should probably store only keys in the database and set an expire parameter on the cache server. When you hit a database point for which there's no longer a valid key, you clean it from the database. You'll probably need a way to invalidate cache when the primary data changes, removing from both the database and the cache server.
I have been data modelling a hobby application that also needs to deal with geolocation data and have had to try to solve similar problems. The solution will of course depend on the constraints that you have and the actual use cases that are crucial to your application's purpose. I will assume that you have design flexibility to change all aspects of your application. i.e. the technology stack.
note:
... so that I don't have to dip into business logic everytime. The URL is not
going to unique since lat/lng change.
The above is an ambiguous statement, since not dipping into business logic can mean many things. I will assume it means you don't want to make any database queries to retrieve new data that might be similar to the data you already have in the cache. Also assuming that you only want to cache on the server, the following approaches come to mind:
Cache the data between the database and the application.
Database ---> Cache --> App ---> User
In this approach, your application processes all the rest api calls and then decide whether the results in the cache can be used or another database access is required.
Cache the data between the application and the user.
Database --> App ---> Cache ---> User
This approach is a little tricky considering that the url is always changing. So you might need a 'smart caching mechanism' that will process the incoming url and then decide whether the cached data is relevant. The smart caching can be done in a number of ways depending on how your application is implemented. Something like mongodb could be used as a json cache and then each incoming request can be preprocessed to see if the data can just be returned from this cache or redirect to the main application. So the structure might look like this:
Database --> App ---> (Some logic(e.g NodeJS app) + Mongodb) ---> User
conclusion:
Without knowing the architecture of your solution, the critical use cases and the full design constraints, one cannot really suggest a complete solution to this problem. You might have to rethink certain features you are trying to provide and make tough compromises to get things working. Hopefully, the suggestions provided by different people here will be helpful.