xamarin non-english dot and comma calculations (Xamarin multi-language support) - xamarin

We are developing a mobile application using Xamarin cross platform development for Android and iOS, which is reading data from a Bluetooth device that transfers data as a float i.e. 12.22 and it will support multiple languages.
When it's set to English all our calculations are fine, but when set to non-english the calculations go completely wrong. I know what is wrong in non-english languages it's treating the "." as an "," which is means a 12.22 becomes 12,22. Therefore, screwing up our calculations.
I have found similar problems, but they force the complete language to English which means we lose the translations and other fixes look very complex for what must be a simple fix.
Is there a easy fix to this problem, like setting a flag in the Xamarin multi-language support
Update :
With the BLE transfer code, we can see the string but when it convert it we get 6000000 for French or 60 for English.
private async Task<double>
GetDatastoreValue(Plugin.BLE.Abstractions.Contracts.IService service, string param)
{
try
{
var datastore_param_char = await service.GetCharacteristicAsync(Guid.Parse(datastore_param_uid));
var datastore_param_val = await service.GetCharacteristicAsync(Guid.Parse(datastore_value_uid));
await datastore_param_char.WriteAsync(Encoding.ASCII.GetBytes(param));
byte[] result = await datastore_param_val.ReadAsync();
string rslt = Encoding.ASCII.GetString(result);
Debug.WriteLine("GetDatastoreValue -> result " + result);
double val = Convert.ToDouble(rslt);
Debug.WriteLine("GetDatastoreValue -> val -> "+ val);
return val;
}
catch
{
return 0.0;
}
}

instead of using this
double val = Convert.ToDouble(rslt);
do this
double val = Double.Parse(rslt, CultureInfo.InvariantCulture);
this will force it to evaluate "123.45" using the decimal separator, regardless of what the user's local culture might be set to

Related

TDirectory::GetFiles listing ignoring case on iOS (FMX, C++)

The code below lists files that have extension .cfg and it works fine on Win32. But, on iOS if i have a file that a user named with caps for the extension (e.g. test.CFG) then i miss it. I found this post using Delphi that might work using TDirectory::TFilterPredicate but i don't know how to implement in C++Builder.
TStringDynArray list;
TSearchOption searchOption;
UnicodeString DocsPath;
int lenDocsFolder;
DocsPath = System::Ioutils::TPath::GetDocumentsPath();
lenDocsFolder = DocsPath.Length();
searchOption = TSearchOption::soTopDirectoryOnly;
try
{
list = TDirectory::GetFiles(DocsPath, "*.cfg", searchOption);
}
catch (...)
{
ShowMessage("Incorrect path or search mask");
return;
}
I suppose i can just run a *.cfg block of code followed by a *.CFG but i'm hoping there is a cleaner approach.
Sorry, but I'm not used to C++. But this applies to both C++ and Delphi.
You are calling:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption): TStringDynArray;
If you instead call this overloaded version:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption;
const Predicate: TFilterPredicate): TStringDynArray;
you should be able to get what you need.
The TFilterPredicate type is defined as:
TFilterPredicate = reference to function(
const Path: string;
const SearchRec: TSearchRec): Boolean;
and should be the correct way to override the way files are matched.
I tried the Using a Lambda Expression from the link Remy posted in comment. I got an E2188 Expression syntaxerror until i disabled the classic Borland compiler. The code works great for simple predicate (on both Win32 and iOS).
String ext(".cfg");
files = TDirectory::GetFiles(CalcPath,
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
Now, how do i modify the extension string to return results for both .cfg and .CFG at same time?
String ext(".cfg"); // works fine
String ext(".cfg;.CFG"); // finds nothing

How do you convert optional text input to Int in Swift 2, Xcode 7 beta using if let - toInt does not work

I'm having trouble converting optional input String to Int in order to do calculations on it.
let odoField = UITextField() // allows entry of text to iOS field
odoField.text = "12500" // simulated input
let odoString = odoField.text
// now here is where I get trouble...
if let odoInt = odoString.toInt() {
distance = Double(odoInt)
}
Apparently the toInt suffix is no longer part of Swift. I have tried the following:
if let odoInt = Int(odoString)() {
But then I get the error "Optional type String? is not unwrapped" and a suggestion to put a ! or ?, as in:
if let odoInt = Int(odoString!)() {
But then I STILL get the euro about unwrapping, with the suggestion that I add yet another !, then when I do that, another error that I get rid of the parens, like this:
if let odoInt = Int(odoString!)! {
And then I get ANOTHER error that "Initializer for conditional binding must have Optional type, not 'Int'."
I'm trying to create conditional unwrapping, here.
Help!
First thing to understand is that UITextField.text returns an optional string, so in your code, odoString is of type String?. Also, keep in mind that the Int constructor takes a String, not a String? so you have to unwrap the String? before you can use it. Just putting a ! after the variable (as in Int(odoString!)) will crash your app if the odoString is nil. Better would be something like this:
if let s = odoString, odoInt = Int(s) {
// odoInt is of type Int. It is guaranteed to have a value in this block
}
I've tested Daniel T's answer and it worked.
I have a situation where I want to get the result of a text field back as an optional Int. You can extend this to cover your case using the following code:
let odoInt = odoField.text != nil ? Int(odoField.text!) : nil
if let odoInt = odoInt {
// Use unwrapped odoInt here
}
Another option - for a more compact solution - is to use a flatMap:
let number = odoString.flatMap { Double($0) } ?? 0.0
In fact, it appears that the answer in Swift 2 (Xcode 7 beta 6) is simpler than anything above. The code does not choke on a nil value for odoString when I do e.g. the following:
if let odoInt = Int(odoString!) {
distance = Double(odoInt)
}
I therefore surmise, barring deeper knowledge to the contrary, that the compiler does treat this as "if the statement is True (the right side is valid), then define and initialize the variable, and continue with execution." I welcome further feedback. This does render unnecessary a lot of the extra code that is suggested above.

No return of "yield return WWW" method in the second run

I'm tracking the following method in Unity3D environment:
(called through StartCoroutine)
private IEnumerator post(string s) {
Debug.Log("Posting to Server: " + s);
WWWForm form = new WWWForm();
form.AddField("data", s);
WWW yaPoster = new WWW(YMCA_URL,form);
Debug.log("11111");
yield return yaPoster;
Debug.log("22222");
if(yaPoster.error != null) {
Debug.Log(yaPoster.error);
}
else {
Debug.Log(yaPoster.text);
}
yaPoster = null;
}
It works well for every first time (saw yaPoster.text from log console), but never can see the "11111" or "22222" in the followed calls.
(Not) surprisingly, things run well on my iPod device with the built iOS Xcode project.
Any specific settings I should apply for my Unity3D environment so that I don't need to debug my code only with the real device?
Looks like it should work just fine!
A wild guess: Turn off Collapse in the Console? Could be that you're just not seeing it the second time because identical messages are not being shown if Collapse is enabled
If you want to keep Collapse enabled, change your Debug.Logs to include Time.time like this:
Debug.Log(Time.time + ": " + "11111"); //adding some uniqueness to keep it from collapsing
(Sorry, don't have enough rep to post this as a comment)

How do I downsample a control rate variable to a scalar value?

In SuperCollider: How do I downsample a control rate variable to a scalar value?
For instance, I have a scalar global called ~delay and a few functions care about that value. They assume it is a scalar. I wanted to set a envelope generator on that variable in order to change it via a control rate variable. Or use MouseX.kr, if I could convert a single value of MouseX.kr to a scalar value I would be happy.
Assume that I cannot refactor the code to allow for a k-rate global and thus I need to sample or downsample a single value from a control rate variable.
I can't do this:
MouseX.kr(1, 4, 1).rand.wait;
But I'd be happy with this:
downSample(MouseX.kr(1, 4, 1)).rand.wait;
Or
~mousex = MouseX.kr(1, 4, 1)
...
downSample(~mousex).rand.wait
This is the classic SuperCollider language-vs-server issue. You want to use MouseX (which represents the server's knowledge of mouse position) in a language-side calculation. ("Why the split? Why can't the language know it using the same object?" - well, imagine the two processes are running on different machines - different mice...)
To get the mouse position in the language, it's better to use one of:
Platform.getMouseCoords // SC up to 3.6
GUI.cursorPosition // SC recent versions
If you're sure you want to use server data in the language, then your own answer about sending via a Bus is one way to do it. Recent versions of SuperCollider have methods
Bus.getSynchronous
Bus.setSynchronous
which rely on the new "shared memory interface" between language and server. If the two are on the same machine, then this can be a nice way to do it which avoids the latency of asynchronously requesting the info.
After much research I came up with 1 solution: use a control Bus to grab values. We take a function as input (f) and then play it to a bus.
We then read from that bus by calling the get method on the bus and providing function that allows us to extract the value from the function thrown in.
~mkscalarfun = {
arg f={ 0 };
var last = 0.0;
var mbus = Bus.control(s, 1);
var pf = f.play(s,mbus);
var scalarf = {
mbus.get({|v| last = v;});
last;
};
scalarf; // This is a function
};
// Create a closure that includes the bus
~mousescalarf = ~mkscalarfun.({ MouseX.kr(1, 4, 1); });
~mousescalarf.();
~mousescalarf.().rand.wait;
I am not sure how idiomatic this solution or if it is appropriate or how well it performs.
One problem with this solution is that pf is hidden and thus you can't stop it.
One alternative is to use an OO solution where you make a class in your extension directory:
MakeScalarKR {
var last;
var mbus;
var pf;
var f;
*new { arg sbase,f;
^super.new.init(sbase,f)
}
init {
arg sbase,myf;
f = myf;
last = 0.0;
mbus = Bus.control(sbase, 1);
pf = f.play(sbase, mbus);
}
v {
mbus.get({|x| last=x;});
^last
}
free {
pf.free
}
}
Then you can invoke this class like so:
~mkr = MakeScalarKR(s,{ MouseX.kr(10,400,1) });
~mkr.v()

Detect iPhone 24-Hour time setting

I'm using a UIDatePicker to select a time. I am also customising the background of the picker, however I need 2 different images depending on whether the user is using 12 hour mode (which displays AM/PM column) or 24 hour mode.
How can I detect the users setting for the 12/24 hour time?
Thanks
Even shorter than the others:
NSString *format = [NSDateFormatter dateFormatFromTemplate:#"j" options:0 locale:[NSLocale currentLocale]];
BOOL is24Hour = ([format rangeOfString:#"a"].location == NSNotFound);
Explanation
The string formatting character to represent the am/pm symbol is "a", as documented in Unicode Locale Markup Language – Part 4: Dates.
The same document also explains the special template symbol "j":
This is a special-purpose symbol. It must not occur in pattern or skeleton data. Instead, it is reserved for use in skeletons passed to APIs doing flexible date pattern generation. In such a context, it requests the preferred hour format for the locale (h, H, K, or k), as determined by whether h, H, K, or k is used in the standard short time format for the locale. In the implementation of such an API, 'j' must be replaced by h, H, K, or k before beginning a match against availableFormats data. Note that use of 'j' in a skeleton passed to an API is the only way to have a skeleton request a locale's preferred time cycle type (12-hour or 24-hour).
The NSString method dateFormatFromTemplate:options:locale: is described in Apple's NSDateFormatter documentation:
Returns a localized date format string representing the given date format components arranged appropriately for the specified locale.
So, what that method will do is turn the #"j" you pass in as a template in to a format string suitable for NSDateFormatter. If this string contains the am / pm symbol #"a" in it anywhere, then you know the locale (and other user settings being interrogated by the OS for you) wants am / pm to be displayed.
Swift (3.x) version of two most popular solutions in form of Date extension :
extension Date {
static var is24HoursFormat_1 : Bool {
let dateString = Date.localFormatter.string(from: Date())
if dateString.contains(Date.localFormatter.amSymbol) || dateString.contains(Date.localFormatter.pmSymbol) {
return false
}
return true
}
static var is24HoursFormat_2 : Bool {
let format = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.autoupdatingCurrent)
return !format!.contains("a")
}
private static let localFormatter : DateFormatter = {
let formatter = DateFormatter()
formatter.locale = Locale.autoupdatingCurrent
formatter.timeStyle = .short
formatter.dateStyle = .none
return formatter
}()
}
Usage :
Date.is24HoursFormat_1
Date.is24HoursFormat_2
Swift (2.0) version of two most popular solutions in form of NSDate extension :
extension NSDate {
class var is24HoursFormat_1 : Bool {
let dateString = NSDate.localFormatter.stringFromDate(NSDate())
if dateString.containsString(NSDate.localFormatter.AMSymbol) || dateString.containsString(NSDate.localFormatter.PMSymbol) {
return false
}
return true
}
class var is24HoursFormat_2 : Bool {
let format = NSDateFormatter.dateFormatFromTemplate("j", options: 0, locale: NSLocale.autoupdatingCurrentLocale())
return !format!.containsString("a")
}
private static let localFormatter : NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.locale = NSLocale.autoupdatingCurrentLocale()
formatter.timeStyle = .ShortStyle
formatter.dateStyle = .NoStyle
return formatter
}()
}
Please note that Apple says following on NSDateFormatter (Date Formatters) :
Creating a date formatter is not a cheap operation. If you are likely
to use a formatter frequently, it is typically more efficient to cache
a single instance than to create and dispose of multiple instances.
One approach is to use a static variable.
Thats the reason for static let
Secondly you should use NSLocale.autoupdatingCurrentLocale() ( for is24HoursFormat_1 ), that way you will always get the actual current state.
one
two
three
and there's probably many, many more...

Resources