What is the best way to manage number with currency? - iphone

In my application it's possible to store a price for every object and the user can also choose its preferred currency.
What is the best way to store and manage number with currency in iPhone SDK?
More infos about my app:
It uses Core Data.
Number that can be stored must be of type xxx.xx (e.g. 100.00).
How can I sort these numbers ascending or descending?
What kind of attribute I must set in my entity to store a number like this?
Have you got links, docs, source or guides to show me examples? I never user number with currency, then I've got some problems with them :)
Thanks a lot,
Matthew

Store it in GP (gold pieces) with a conversion factor ;)
It doesn't look like there's a datatype for currency, so storing the number and decimal part, and a setting for the current currency, is probably as good as you're going to get. See this: HowTo for newbie: Managing currency in iPhone app

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.

Does getPriceAmountMicros() include local taxes for skus of type subscription?

I've been using the Android billing client for a while now and always display the prices using getPriceAmountInMicros() from the SkuDetails object returned from the billing client.
Often we get complains from some of the customers that the price we display is not the same price they're paying. I've always assumed this is due to local taxes and that the Google play Store doesn't return the prices with local taxes included.
However, going to the documentation of getPriceAmountInMicros() things start to get a bit fuzzy. In particular this section:
This value represents the localized, rounded price for a particular currency.
What is a "localized price"? Is this including taxes? I cannot find any explicit place where it says this includes taxes or that it doesn't. By contrast the documentation for getPrice() explicitly states that the price does not include taxes.
Looking into a completely different resource, yet connected to a sku, one can see the same method - getPriceAmountInMicros(). In this method, it's explicitly stated that the price does not include taxes. It would seem odd to me that they would choose to name the method in a SkyDetails object the same, but have different semantics. Nevertheless, I want to be sure and would highly appreciate your help!
Thanks for pointing this out.
Because the QPS of computing taxes during skuDetails queries would be high, our servers defer tax computation to the purchase flow. So unless you need getPriceAmountMicros() for, say, refunds; you should simply use getPrice().

perfect fit for a Postgres function or not (and how)?

I'm working on this kind of data structure :
Now, say I have to search for products that are < 90 EUR, it should only returns the product "item2". On the other hand, if I search for products that are == 100 EUR, I should only returns the product "item1".
I have 60 000 products and 16 currencies, so I just can't convert all products in all currencies on a daily basis (as the currency rates updates daily) only to be able to perform this search.
I have 2 questions :
is this use case a good fit for a Postgres function ? Is there any other good and sustainable solution if not ?
if a postgres function is the solution. Given that I'm using Ruby on Rails (4.2) and the search requests (on products sizes, colors etc...) are chained using ActiveRecord : is the call to the DB function still chainable and usable in AR ?
Thanks for your help
Using a function for this is a terrible idea, because performance will suffer greatly: the exchange rates will change over time, rendering your indexes useless.
Further, it's a terrible idea to store a single price per item. Thing psychological prices and tax considerations: if something is €99.99 including VAT in the Eurozone, it'll probably make sense to sell it for $99.99 plus sales tax in the US. No amount of exchange rate manipulation using functions or other will change that. (Compare the prices of Apple in the US, in France, in the UK, etc.).
For each item, associate a price in Euros, one in Dollars, etc. -- each with a currency_id, and have the exchange rates reside in a separate table. Or create some kind of price-list table in which you associate prices based on currency (e.g. €99 = $99) to a price_id, and associate the products (it's actually the SKU, btw) to their corresponding price_id.
You can fill this data in semi-automatically using an exchange rate table, and periodically update them using one as well. But really: do reserve the ability to manually set prices, make sure you mark prices as including or excluding tax. And when it comes to taxes, don't forget that tax rates are different from a place to the next and from a product to the next.
For the record, I ended up creating a new column "price_eur" in the "products" table where I convert each price to EUR whatever is the original currency. Doing so I can perform a consistent search based on this price_eur column.
I just wanted to know if there was an alternative solution but looks like there is no other simple way...

Censor certain words and images

My question is how can i censor bad language and nudity images on my application, is there some sort of a framework that can filter the content that is introduced by the user? what are you, IOS experts, using at this moment to solve this problem?
There are two parts to your question: 1) Censoring text, 2) Censoring images.
In the case of text, you could store a dictionary and match user input to words that you want to censor. However how do you define bad language? Words have meaning depending on their context, and software can't determine context. Ie Is saying that someone likes to eat watermelon something that should be censored? Well it could be considered racist if applied to certain groups of people. And that's something your dictionary can't tell.
In the case of images, there is no reliable method to discern nudity via an algorithm. In fact all websites that do image censoring use humans to categorize and censor user supplied images for that reason (And from what I have read its not the best of jobs to have). And even the humans make mistakes. Recently FB rejected an image of a woman In a bath because they mistook her elbow for a naked breast.

Implement "Did you mean?" with Core Data

I'm working on an iOS app. I have a Core Data database with a lot of company names.
When the user insert a company name that does not exist, I would like to show "similar" company names. For example, if the user entered "Aple", I would like to show "Did you mean Apple?".
I know that the technique of finding strings that match a pattern approximately (rather than exactly) is called approximate string matching or, colloquially, fuzzy string searching.
In theory, there are many algorithms, more or less valid: the Levenshtein distance computing algorithm and so on.
But in practice, is there someone who has already implemented something similar that can be used easily with core data?
I found a solution. Use this NSString's category available on GitHub: NSString-DamerauLevenshtein.
Try looking at Soundex, I believe that is part of the core featureset for SQLite, if that is your underlying data store.