问:
Face authentication to unlock my app programmatically
I am developing an android app which uses fingerprint/face recognition for unlocking the app.

I have successfully integrated fingerprint authentication using BiometricPrompt. But didn't know where to start for Face authentication. Any headsup will be really helpful.

Also, Since BiometricPrompt comes with face, fingerprint, and iris, I don't want to use either MLKIT or any third party libraries.

Below is the piece of code I used for Fingerprint authentication.

```<code>new BiometricPrompt
    .Builder(context)
    .setTitle(title)
    .setSubtitle(subtitle)
    .setDescription(description)
    .setNegativeButton(negativeButtonText, context.getMainExecutor(),
                        new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            biometricCallback.onAuthenticationCancelled();
        }
    })
    .build()
    .authenticate(new CancellationSignal(), context.getMainExecutor(),
            new BiometricCallbackV28(biometricCallback));
</code>```

答:
Step1: Add the latest biometric dependency in build.gradle file.

```<code>implementation 'androidx.biometric:biometric:1.0.1'
</code>```

Step2: Add permission for biometric in AndroidManifest.xml file.

```<code><uses-permission android:name="android.permission.USE_BIOMETRIC" />
</code>```

Step3: Create activity_login.xml file and define the Touch ID button's UI.

activity_login.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <RelativeLayout
        android:id="@+id/parent_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="30dp">

        <Button
            android:id="@+id/touch_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/river_blue"
            android:stateListAnimator="@null"
            android:text="Biometric Login"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="16sp" />

    </RelativeLayout>

</layout>
</code>```

Step4: Create LoginActivity.java file to implement the biometric login feature.

LoginActivity.java:

```<code>import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;

import android.os.Build;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.widget.Button;

import androidx.biometric.BiometricManager;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

/**
 * Created by: rajoo.kannaujiya on 02/16/2020
 */
@RequiresApi(api = Build.VERSION_CODES.P)
public class LoginActivity extends AppCompatActivity {
    private static final String KEY_NAME = "KeyName";
    private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
    private static final String FORWARD_SLASH = "/";
    private Button touchButton;

    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        touchButton = findViewById(R.id.touch_button);
        touchButton.setOnClickListener((view) -> onTouchIdClick());
        displayBiometricButton();
    }

    private void onTouchIdClick() {
        getBiometricPromptHandler().authenticate(getBiometricPrompt(), new BiometricPrompt.CryptoObject(getCipher()));
        // Please see the below mentioned note section.
        // getBiometricPromptHandler().authenticate(getBiometricPrompt());
    }

    private boolean isBiometricCompatibleDevice() {
        if (getBiometricManager().canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    private void displayBiometricButton() {
        if (isBiometricCompatibleDevice()) {
            touchButton.setEnabled(false);
        } else {
            touchButton.setEnabled(true);
            generateSecretKey();
        }
    }

    private BiometricManager getBiometricManager() {
        return BiometricManager.from(this);
    }

    private void generateSecretKey() {
        KeyGenerator keyGenerator = null;
        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
                KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setUserAuthenticationRequired(true)
                .setInvalidatedByBiometricEnrollment(false)
                .build();
        try {
            keyGenerator = KeyGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
            e.printStackTrace();
        }
        if (keyGenerator != null) {
            try {
                keyGenerator.init(keyGenParameterSpec);
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            keyGenerator.generateKey();
        }
    }

    private SecretKey getSecretKey() {
        KeyStore keyStore = null;
        Key secretKey = null;
        try {
            keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        if (keyStore != null) {
            try {
                keyStore.load(null);
            } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            try {
                secretKey = keyStore.getKey(KEY_NAME, null);
            } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
                e.printStackTrace();
            }
        }
        return (SecretKey) secretKey;
    }

    private Cipher getCipher() {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + FORWARD_SLASH
                    + KeyProperties.BLOCK_MODE_CBC + FORWARD_SLASH
                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
            try {
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
        }
        return cipher;
    }

    private BiometricPrompt.PromptInfo getBiometricPrompt() {
        return new BiometricPrompt.PromptInfo.Builder()
                .setTitle("Biometric login for my app")
                .setSubtitle("Login with your biometric credential")
                .setNegativeButtonText("cancel")
                .setConfirmationRequired(false)
                .build();
    }

    private void onBiometricSuccess() {
        //Call the respective API on biometric success
        callLoginApi("userName", "password");
    }

    private BiometricPrompt getBiometricPromptHandler() {
        return new BiometricPrompt(this, ContextCompat.getMainExecutor(this),
                new BiometricPrompt.AuthenticationCallback() {

                    @Override
                    public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
                        super.onAuthenticationError(errorCode, errString);
                    }

                    @Override
                    public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
                        super.onAuthenticationSucceeded(result);
                        onBiometricSuccess();
                    }

                    @Override
                    public void onAuthenticationFailed() {
                        super.onAuthenticationFailed();
                    }
                }
        );
    }
}
</code>```

Note: The authentication level for biometric sensors (fingerprint, face, iris) are classified as Strong and Weak. As per Android Compatibility Definition Document (Android CDD), To access the android key store, the authentication level for biometric sensors must be classified as Strong. Since face and iris sensor are classified as Weak category in some of the devices, Hence in those devices face and iris options will not be displayed in the biometric prompt authenticated with CryptoObject.

```<code>getBiometricPromptHandler().authenticate(getBiometricPrompt(), new BiometricPrompt.CryptoObject(getCipher()));
</code>```

If you authenticate the biometric prompt without CryptoObject, Then it will be displayed.

```<code>getBiometricPromptHandler().authenticate(getBiometricPrompt());
</code>```

Body:
I am developing an android app which uses fingerprint/face recognition for unlocking the app.

I have successfully integrated fingerprint authentication using BiometricPrompt. But didn't know where to start for Face authentication. Any headsup will be really helpful.

Also, Since BiometricPrompt comes with face, fingerprint, and iris, I don't want to use either MLKIT or any third party libraries.

Below is the piece of code I used for Fingerprint authentication.

new BiometricPrompt
    .Builder(context)
    .setTitle(title)
    .setSubtitle(subtitle)
    .setDescription(description)
    .setNegativeButton(negativeButtonText, context.getMainExecutor(),
                        new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            biometricCallback.onAuthenticationCancelled();
        }
    })
    .build()
    .authenticate(new CancellationSignal(), context.getMainExecutor(),
            new BiometricCallbackV28(biometricCallback));

Body:
Step1: Add the latest biometric dependency in build.gradle file.

implementation 'androidx.biometric:biometric:1.0.1'

Step2: Add permission for biometric in AndroidManifest.xml file.

<uses-permission android:name="android.permission.USE_BIOMETRIC" />

Step3: Create activity_login.xml file and define the Touch ID button's UI.

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <RelativeLayout
        android:id="@+id/parent_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="30dp">

        <Button
            android:id="@+id/touch_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/river_blue"
            android:stateListAnimator="@null"
            android:text="Biometric Login"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="16sp" />

    </RelativeLayout>

</layout>

Step4: Create LoginActivity.java file to implement the biometric login feature.

LoginActivity.java:

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;

import android.os.Build;
import android.os.Bundle;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.widget.Button;

import androidx.biometric.BiometricManager;

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;

/**
 * Created by: rajoo.kannaujiya on 02/16/2020
 */
@RequiresApi(api = Build.VERSION_CODES.P)
public class LoginActivity extends AppCompatActivity {
    private static final String KEY_NAME = "KeyName";
    private static final String ANDROID_KEY_STORE = "AndroidKeyStore";
    private static final String FORWARD_SLASH = "/";
    private Button touchButton;

    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        touchButton = findViewById(R.id.touch_button);
        touchButton.setOnClickListener((view) -> onTouchIdClick());
        displayBiometricButton();
    }

    private void onTouchIdClick() {
        getBiometricPromptHandler().authenticate(getBiometricPrompt(), new BiometricPrompt.CryptoObject(getCipher()));
        // Please see the below mentioned note section.
        // getBiometricPromptHandler().authenticate(getBiometricPrompt());
    }

    private boolean isBiometricCompatibleDevice() {
        if (getBiometricManager().canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    private void displayBiometricButton() {
        if (isBiometricCompatibleDevice()) {
            touchButton.setEnabled(false);
        } else {
            touchButton.setEnabled(true);
            generateSecretKey();
        }
    }

    private BiometricManager getBiometricManager() {
        return BiometricManager.from(this);
    }

    private void generateSecretKey() {
        KeyGenerator keyGenerator = null;
        KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(
                KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setUserAuthenticationRequired(true)
                .setInvalidatedByBiometricEnrollment(false)
                .build();
        try {
            keyGenerator = KeyGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE);
        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
            e.printStackTrace();
        }
        if (keyGenerator != null) {
            try {
                keyGenerator.init(keyGenParameterSpec);
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            }
            keyGenerator.generateKey();
        }
    }

    private SecretKey getSecretKey() {
        KeyStore keyStore = null;
        Key secretKey = null;
        try {
            keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        } catch (KeyStoreException e) {
            e.printStackTrace();
        }
        if (keyStore != null) {
            try {
                keyStore.load(null);
            } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            try {
                secretKey = keyStore.getKey(KEY_NAME, null);
            } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
                e.printStackTrace();
            }
        }
        return (SecretKey) secretKey;
    }

    private Cipher getCipher() {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + FORWARD_SLASH
                    + KeyProperties.BLOCK_MODE_CBC + FORWARD_SLASH
                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
            try {
                cipher.init(Cipher.ENCRYPT_MODE, getSecretKey());
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            e.printStackTrace();
        }
        return cipher;
    }

    private BiometricPrompt.PromptInfo getBiometricPrompt() {
        return new BiometricPrompt.PromptInfo.Builder()
                .setTitle("Biometric login for my app")
                .setSubtitle("Login with your biometric credential")
                .setNegativeButtonText("cancel")
                .setConfirmationRequired(false)
                .build();
    }

    private void onBiometricSuccess() {
        //Call the respective API on biometric success
        callLoginApi("userName", "password");
    }

    private BiometricPrompt getBiometricPromptHandler() {
        return new BiometricPrompt(this, ContextCompat.getMainExecutor(this),
                new BiometricPrompt.AuthenticationCallback() {

                    @Override
                    public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
                        super.onAuthenticationError(errorCode, errString);
                    }

                    @Override
                    public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
                        super.onAuthenticationSucceeded(result);
                        onBiometricSuccess();
                    }

                    @Override
                    public void onAuthenticationFailed() {
                        super.onAuthenticationFailed();
                    }
                }
        );
    }
}

Note: The authentication level for biometric sensors (fingerprint, face, iris) are classified as Strong and Weak. As per Android Compatibility Definition Document (Android CDD), To access the android key store, the authentication level for biometric sensors must be classified as Strong. Since face and iris sensor are classified as Weak category in some of the devices, Hence in those devices face and iris options will not be displayed in the biometric prompt authenticated with CryptoObject.

getBiometricPromptHandler().authenticate(getBiometricPrompt(), new BiometricPrompt.CryptoObject(getCipher()));

If you authenticate the biometric prompt without CryptoObject, Then it will be displayed.

getBiometricPromptHandler().authenticate(getBiometricPrompt());


来源: stackexchange

问:
Sorting an array of objects using a well known dynamicSort function, but getting this error: "Comparison method violates its general contract"
I am generating an array of calendar events and then (using code I got from user 'Cooper') I am deduplicating the list to create a new array: dedList

```<code>// This code creates a deduplicated array (dedList) from my array 'events' (parts of this code are from Cooper on StackOverflow... and I don't really understand it all)
var dedList=[];
var obj={eA:[]};
for(var i=0;i<events.length;i++) {
  var key=events[i].getTitle() + events[i].getDescription();
  if(!obj.hasOwnProperty(key)) {
    obj[key]={
      title: events[i].getTitle(),
      description: events[i].getDescription(),
      guest_list: events[i].getGuestList(),
      guests: events[i].getGuestList().length,
      start: events[i].getStartTime(),
      end: events[i].getEndTime(),
      recurs: events[i].isRecurringEvent(),
      duration: "",
      creator: events[i].getCreators(),
      color: events[i].getColor() ,
      copies: 0,
      category: "",
    };
    obj.eA.push(key);
  }else{
    obj[key].copies+=1; //count the copies
  }
}
for(var i=0;i<obj.eA.length;i++) {
  dedList.push(obj[obj.eA[i]]);
}
</code>```

This is working perfectly, but I'm using some well shared code to sort dedList by "category" and it's generating error I've never seen before: "Comparison method violates its general contract." Here's the line causing the error, followed by the function I am using:

```<code>dedList.sort(dynamicSort("category")); // this line generates the error

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}
</code>```

Any suggestions? I'm pretty new to google scripting so I don't completely understand how the dynamicSort function works, and that is making it hard for me to debug the error. Thanks!

MCVE:

```<code>function sortTest() {
  var arr = [];
  for (i = 0; i < 50; ++i) {
    arr.push({ a: '' }, {}, { a: {} });
  }
  Logger.log(arr.sort(dynamicSort('a')));
}
function dynamicSort(property) {
    var sortOrder = 1;
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}
</code>```

Engine: Rhino (Old)

Error:

Comparison method violates its general contract

答:
Have you tried dedList.sort(function(a,b){return a.category-b.category});

or vice-versa dedList.sort(function(a,b){return b.category-a.category});

also you should remove the trailing comma from this line category: "",

If that doesn't work I'd consider making life easier by initializing all of the categories with "AAAAA";

ContentLicense: CC BY-SA 4.0

Body:
I am generating an array of calendar events and then (using code I got from user 'Cooper') I am deduplicating the list to create a new array: dedList

// This code creates a deduplicated array (dedList) from my array 'events' (parts of this code are from Cooper on StackOverflow... and I don't really understand it all)
var dedList=[];
var obj={eA:[]};
for(var i=0;i<events.length;i++) {
  var key=events[i].getTitle() + events[i].getDescription();
  if(!obj.hasOwnProperty(key)) {
    obj[key]={
      title: events[i].getTitle(),
      description: events[i].getDescription(),
      guest_list: events[i].getGuestList(),
      guests: events[i].getGuestList().length,
      start: events[i].getStartTime(),
      end: events[i].getEndTime(),
      recurs: events[i].isRecurringEvent(),
      duration: "",
      creator: events[i].getCreators(),
      color: events[i].getColor() ,
      copies: 0,
      category: "",
    };
    obj.eA.push(key);
  }else{
    obj[key].copies+=1; //count the copies
  }
}
for(var i=0;i<obj.eA.length;i++) {
  dedList.push(obj[obj.eA[i]]);
}

This is working perfectly, but I'm using some well shared code to sort dedList by "category" and it's generating error I've never seen before: "Comparison method violates its general contract." Here's the line causing the error, followed by the function I am using:

dedList.sort(dynamicSort("category")); // this line generates the error

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property]  b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Any suggestions? I'm pretty new to google scripting so I don't completely understand how the dynamicSort function works, and that is making it hard for me to debug the error. Thanks!

MCVE:

function sortTest() {
  var arr = [];
  for (i = 0; i < 50; ++i) {
    arr.push({ a: '' }, {}, { a: {} });
  }
  Logger.log(arr.sort(dynamicSort('a')));
}
function dynamicSort(property) {
    var sortOrder = 1;
    return function (a,b) {
        var result = (a[property]  b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Engine: Rhino (Old)

Error:

Comparison method violates its general contract


问:
regexp and rails validations
I have two customs validations :

```<code>  def validate_email
    regexp = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+"
    if sleep_email.present? && !sleep_email.match(regexp)
      errors.add(:sleep_email, "l'email indiqué semble ne pas avoir le bon format")
    end
  end

  def validate_website
    regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
    if website.present? && !website.match(regexp)
      errors.add(:website, "l'url de votre site web doit avoir la forme de http://votresite.com")
    end
  end
</code>```

But yo@yo and http://website are valids. What's wrong ?

答:
You're building regexes using strings. Strings and regexes have different quoting. You're effectively double escaping. Things like \. are turned into a plain ..

```<code># This results in the regex /a.c/
p "abc".match?("a\.c")  # true

# This results in the desired regex /a\.c/
p "abc".match?("a\\.c")  # true

# This avoids the string escaping entirely.
p "abc".match?(%r{a\.c})  # false
</code>```

To avoid this double escaping, use /.../ or %r{...} to create regexes.

Don't try to validate email with a regex. Instead, use the validates_email_format_of gem which provides a proper validator you can use on any attribute.

```<code>validates :sleep_email, presence: true, email_format: true
</code>```

If you want to see how to fully validate an email address, look at the source.

Your URL regex does work.

```<code>regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
p "http://website".match?(regexp)  # true
</code>```

http://website is valid URL syntax. It's not URL's job to check the validity of the host.

If you also want to validate parts of the URL your regex will get increasingly complex. Instead, parse the URL with URI and then check its individual pieces as you like.

Here's a custom validator I whipped up which parse the URI, checks it's an allowed scheme, and does a very rudimentary check on the host.

```<code>class UrlValidator < ActiveModel::EachValidator
  ALLOWED_SCHEMES = ['http', 'https']

  private def allowed_schemes
    options[:allowed_schemes] || ALLOWED_SCHEMES
  end

  def validates_each(record, attribute, value)
    uri = URI(value)

    if !allowed_schemes.include?(uri.scheme)
      record.errors.add(attribute, :scheme_not_allowed, message: "Scheme #{uri.scheme} is not allowed")
    end

    # Has to have at least xxx.yyy
    # This is a pretty sloppy host check.
    if !uri.host.match?(/\w+\.\w+/)
      record.errors.add(attribute, :host_not_allowed, message: "Host #{uri.host} is not allowed")
    end
  rescue URI::Error
    record.errors.add(attribute, :not_a_uri)
  end
end
</code>```

```<code>validates :website, url: true
</code>```

If you wanted to allow other schemes, like ftp...

```<code>validates :website, url: { allowed_schemes: ['http', 'https', 'ftp'] }
</code>```

If you wanted true domain validation, you could add a DNS lookup.

```<code>  begin
    Resolv::DNS.open do |dns|
      dns.getaddress(uri.host) }
    end
  rescue Resolv::ResolvError
    record.errors.add(attribute, :invalid_host, { message: "#{uri.host} could not be resolved" }
  end
</code>```

However, this lookup has a performance impact.

Title: regexp and rails validations

Body:
I have two customs validations :

  def validate_email
    regexp = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+"
    if sleep_email.present? && !sleep_email.match(regexp)
      errors.add(:sleep_email, "l'email indiqué semble ne pas avoir le bon format")
    end
  end

  def validate_website
    regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
    if website.present? && !website.match(regexp)
      errors.add(:website, "l'url de votre site web doit avoir la forme de http://votresite.com")
    end
  end

But yo@yo and http://website are valids. What's wrong ?

Body:
You're building regexes using strings. Strings and regexes have different quoting. You're effectively double escaping. Things like \. are turned into a plain ..

# This results in the regex /a.c/
p "abc".match?("a\.c")  # true

# This results in the desired regex /a\.c/
p "abc".match?("a\\.c")  # true

# This avoids the string escaping entirely.
p "abc".match?(%r{a\.c})  # false

To avoid this double escaping, use /.../ or %r{...} to create regexes.

Don't try to validate email with a regex. Instead, use the validates_email_format_of gem which provides a proper validator you can use on any attribute.

validates :sleep_email, presence: true, email_format: true

If you want to see how to fully validate an email address, look at the source.

Your URL regex does work.

regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
p "http://website".match?(regexp)  # true

http://website is valid URL syntax. It's not URL's job to check the validity of the host.

If you also want to validate parts of the URL your regex will get increasingly complex. Instead, parse the URL with URI and then check its individual pieces as you like.

Here's a custom validator I whipped up which parse the URI, checks it's an allowed scheme, and does a very rudimentary check on the host.

class UrlValidator < ActiveModel::EachValidator
  ALLOWED_SCHEMES = ['http', 'https']

  private def allowed_schemes
    options[:allowed_schemes] || ALLOWED_SCHEMES
  end

  def validates_each(record, attribute, value)
    uri = URI(value)

    if !allowed_schemes.include?(uri.scheme)
      record.errors.add(attribute, :scheme_not_allowed, message: "Scheme #{uri.scheme} is not allowed")
    end

    # Has to have at least xxx.yyy
    # This is a pretty sloppy host check.
    if !uri.host.match?(/\w+\.\w+/)
      record.errors.add(attribute, :host_not_allowed, message: "Host #{uri.host} is not allowed")
    end
  rescue URI::Error
    record.errors.add(attribute, :not_a_uri)
  end
end

validates :website, url: true

If you wanted to allow other schemes, like ftp...

validates :website, url: { allowed_schemes: ['http', 'https', 'ftp'] }

If you wanted true domain validation, you could add a DNS lookup.

  begin
    Resolv::DNS.open do |dns|
      dns.getaddress(uri.host) }
    end
  rescue Resolv::ResolvError
    record.errors.add(attribute, :invalid_host, { message: "#{uri.host} could not be resolved" }
  end

However, this lookup has a performance impact.


问:
formencode nesting custom validators within schema
I want to nest my custom validators within my schema, like this:

```<code>MySchema(Schema):
    class MyValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...
    class MyOtherValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...

    field_foo = All(validators.NotEmpty(),
                    MyValidator())
    field_bar = All(validators.NotEmpty(),
                    MyOtherValidator())
</code>```

However, it seems to think that MyValidator and MyOtherValidator are fields b/c it's form_errors contain:

```<code>{
  'MyValidator': 'Missing value',
  'MyOtherValidator': 'Missing value'
}
</code>```

If I don't nest them, they seem fine.  What am I missing?

答:
In python, anything that you define in your class is a field.
Be it static variables, variables set with self, methods or classes.
If you want to "hide" the classes, or make them "less public", as is probably the right wording in the python dictionary, you should start their names with __.

```<code>>>> dir(X())
['A', '_B', '_X__C', '__doc__', '__module__']
>>> class X:
...     class A: pass
...     class __B: pass
...     c = 0
...     __d = 1
...
>>> dir(X())
['A', '_X__B', '_X__d', '__doc__', '__module__', 'c']
</code>```

As you can see, there is a loophole for this kind of privacy, but most automatic tools will recognize that you are trying to make something private.

ContentLicense: CC BY-SA 3.0

Body:
I want to nest my custom validators within my schema, like this:

MySchema(Schema):
    class MyValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...
    class MyOtherValidator(validators.FancyValidator):
        def _to_python(self, value, state):
            ...

    field_foo = All(validators.NotEmpty(),
                    MyValidator())
    field_bar = All(validators.NotEmpty(),
                    MyOtherValidator())

However, it seems to think that MyValidator and MyOtherValidator are fields b/c it's form_errors contain:

{
  'MyValidator': 'Missing value',
  'MyOtherValidator': 'Missing value'
}

If I don't nest them, they seem fine.  What am I missing?

Body:
In python, anything that you define in your class is a field.
Be it static variables, variables set with self, methods or classes.
If you want to "hide" the classes, or make them "less public", as is probably the right wording in the python dictionary, you should start their names with __.

>>> dir(X())
['A', '_B', '_X__C', '__doc__', '__module__']
>>> class X:
...     class A: pass
...     class __B: pass
...     c = 0
...     __d = 1
...
>>> dir(X())
['A', '_X__B', '_X__d', '__doc__', '__module__', 'c']

As you can see, there is a loophole for this kind of privacy, but most automatic tools will recognize that you are trying to make something private.


问:
how do I get pixel values or windows x/y positions to style accordingly to those coordinates?
How can I get an element to change it's style according to my mouse position in that element during a hover?

For example:

If I hover my mouse on the top-left part (maybe 20% from top and 20% left) of the div, I would like to apply style A on this div but if I hover on the bottom-right part (maybe 20% from bottom and 20% from right) of the div I would like to apply style B instead.

The main question is:

How do I get those

20% from top and 20% left

20% from bottom and 20% from right

coordinates to use with div:hover selector?

答:
For the solutions below, let's say we have an element with 400px of width and 300px of height.

```<code><div class="element"></div>
</code>```

```<code>.element {
  height: 300px;
  width: 400px;
  background: #333;
}
</code>```

Solution 1: with CSS only

Solving the example you gave, we have to wrap the div in a container element with two spans before the div as auxiliary elements.

```<code><div class="container">
  <span class="left-top-20"></span>
  <span class="right-bottom-20"></span>
  <div class="element"></div>
</div>
</code>```

Then, we position the  elements in the corners. For this we set position: relative to the container and position: absolute to the spans and top, right, bottom and left properties.

Finally, hovering the spans will affect the .element style using general sibling selector ~;

```<code>.container {
  display: inline-block;
  position: relative;
}
.container span {
  width: 20%;
  height: 20%;
  position: absolute;
}
.left-top-20 {
  left: 0;
  top: 0;
}
.right-bottom-20 {
  right: 0;
  bottom: 0;
}
.left-top-20:hover ~ .element {
  background-color: red;
}
.right-bottom-20:hover ~ .element {
  background-color: green;
}
.element {
  height: 300px;
  width: 400px;
  background: #333;
}
</code>```

A drawback of this is that the spans will be in front of the div element, so they will prevent any interaction with what is underneath, such as selecting text or clicking any button.

Solution 2: with JavaScript

For this solution, you don't need container or auxiliary elements.
First, you add a listener for hovering the element, the mousemove event listener. Every time the mouse moves inside the element, its height and width will be stored, as well as the position of the mouse inside it.

Lastly, the conditional and calculation will be made to check if the position is where you want it to be, adding classes to style the div, or removing them.

```<code>.element {
  height: 300px;
  width: 400px;
  background: #333;
}
.red {
  background: red;
}
.green {
  background: green;
}
</code>```

```<code>document.querySelector('.element').addEventListener('mousemove', function(e) {

  var elementWidth = this.offsetWidth;
  var elementHeight = this.offsetHeight;
  var positionHorizontal = e.offsetX;
  var positionVertical = e.offsetY;

  if (positionHorizontal <= elementWidth * 0.2 && positionVertical <= elementHeight * 0.2) {
    this.classList.add('red');
  } else if (positionHorizontal >= (elementWidth - (elementWidth * 0.2)) && positionVertical >= (elementHeight - (elementHeight * 0.2))) {
    this.classList.add('green');
  } else {
    this.classList.remove('red', 'green');
  }

});
</code>```

Another event listener is also needed to check if the mouse has left the element. This is for situations where the mouse was in one of the corners before leaving, so the style will be removed. Otherwise, the style would remain applied even with the mouse out.

```<code>document.querySelector('.element').addEventListener('mouseleave', function(e) {
  this.classList.remove('red', 'green');
});
</code>```

A disadvantage of this approach is that it has a worse performance than the first solution.

Body:
For the solutions below, let's say we have an element with 400px of width and 300px of height.

<div class="element"></div>

.element {
  height: 300px;
  width: 400px;
  background: #333;
}

Solution 1: with CSS only

Solving the example you gave, we have to wrap the div in a container element with two spans before the div as auxiliary elements.

<div class="container">
  <span class="left-top-20"></span>
  <span class="right-bottom-20"></span>
  <div class="element"></div>
</div>

Then, we position the <span> elements in the corners. For this we set position: relative to the container and position: absolute to the spans and top, right, bottom and left properties.

Finally, hovering the spans will affect the .element style using general sibling selector ~;

.container {
  display: inline-block;
  position: relative;
}
.container span {
  width: 20%;
  height: 20%;
  position: absolute;
}
.left-top-20 {
  left: 0;
  top: 0;
}
.right-bottom-20 {
  right: 0;
  bottom: 0;
}
.left-top-20:hover ~ .element {
  background-color: red;
}
.right-bottom-20:hover ~ .element {
  background-color: green;
}
.element {
  height: 300px;
  width: 400px;
  background: #333;
}

A drawback of this is that the spans will be in front of the div element, so they will prevent any interaction with what is underneath, such as selecting text or clicking any button.

Solution 2: with JavaScript

For this solution, you don't need container or auxiliary elements.
First, you add a listener for hovering the element, the mousemove event listener. Every time the mouse moves inside the element, its height and width will be stored, as well as the position of the mouse inside it.

Lastly, the conditional and calculation will be made to check if the position is where you want it to be, adding classes to style the div, or removing them.

.element {
  height: 300px;
  width: 400px;
  background: #333;
}
.red {
  background: red;
}
.green {
  background: green;
}

document.querySelector('.element').addEventListener('mousemove', function(e) {

  var elementWidth = this.offsetWidth;
  var elementHeight = this.offsetHeight;
  var positionHorizontal = e.offsetX;
  var positionVertical = e.offsetY;

  if (positionHorizontal <= elementWidth * 0.2 && positionVertical <= elementHeight * 0.2) {
    this.classList.add('red');
  } else if (positionHorizontal >= (elementWidth - (elementWidth * 0.2)) && positionVertical >= (elementHeight - (elementHeight * 0.2))) {
    this.classList.add('green');
  } else {
    this.classList.remove('red', 'green');
  }

});

Another event listener is also needed to check if the mouse has left the element. This is for situations where the mouse was in one of the corners before leaving, so the style will be removed. Otherwise, the style would remain applied even with the mouse out.

document.querySelector('.element').addEventListener('mouseleave', function(e) {
  this.classList.remove('red', 'green');
});

A disadvantage of this approach is that it has a worse performance than the first solution.


问:
Angular 8 custom framework
I wanted to design and develop a framework on top of Angular 8/9 which should serve for multiple applications which can share common code across all the applications.

This application serves for various countries, the rules from country to country may same or differ.

UI-Components: custom UI components which is exposed as node module, In future which can be upgraded and published to all the apps.
Core : which should have common, core, abstract code for all the applications.

Country-1 code : Country-1 is Implementation of Core, which will reuse and extend them where ever required.

Country-N code : Country-N is Implementation of Core, which will reuse and extend them where ever required.

I have below structure in consideration but i wanted to parameterize by country, i mean on generation dist, the respective dist should not package with other country code.

https://medium.com/disney-streaming/combining-multiple-angular-applications-into-a-single-one-e87d530d6527

The design should be close for modification and open for extension.
enter image description here
I appreciate your response.

答:
Since I cannot post an this much characters as a comment, I am posting this as an answer. It might not be exactly what you need, but I think it is a good starting point.

If you have the following project structure

```<code>--app
  --components
    --component1
      --country1
      --country2
    --component2
      --country1
      --country2
</code>```

And if you want to have different production builds for each country, you want to update the angular.json file so that it will include specific file/folder transfer configurations for each country. For example, the production build has this configuration:

```<code>"production": {
   "fileReplacements": [
       {
           "replace": "src/environments/environment.ts",
           "with": "src/environments/environment.prod.ts"
       }
    ],
    ...
}
</code>```

Then you will need to add the country specific configurations:

```<code>"country1": {
   "assets": [
       {
           "input": "src/app/components/component1/country1",
           "output": "components/component1"
       },
       {
           "input": "src/app/components/component2/country1",
           "output": "components/component2"
       }
   ]
    ...
}
</code>```

Then you can run a production build with the command:

ng build --prod --configuration country1

This will copy the script files in the assets folder and simply load them from there. I think this will copy over the scripts as they are (without minification etc.).

I hope this helps.

Title: Angular 8 custom framework

Body:
Since I cannot post an this much characters as a comment, I am posting this as an answer. It might not be exactly what you need, but I think it is a good starting point.

If you have the following project structure

--app
  --components
    --component1
      --country1
      --country2
    --component2
      --country1
      --country2

And if you want to have different production builds for each country, you want to update the angular.json file so that it will include specific file/folder transfer configurations for each country. For example, the production build has this configuration:

"production": {
   "fileReplacements": [
       {
           "replace": "src/environments/environment.ts",
           "with": "src/environments/environment.prod.ts"
       }
    ],
    ...
}

Then you will need to add the country specific configurations:

"country1": {
   "assets": [
       {
           "input": "src/app/components/component1/country1",
           "output": "components/component1"
       },
       {
           "input": "src/app/components/component2/country1",
           "output": "components/component2"
       }
   ]
    ...
}

Then you can run a production build with the command:

ng build --prod --configuration country1

This will copy the script files in the assets folder and simply load them from there. I think this will copy over the scripts as they are (without minification etc.).

I hope this helps.


问:
Java String Split by \\s+ and by String Array
In this code a user will input some text. It then needs to be split by whitespace - I am currently using:

for (String inputSplit : userInput.split("[\\s+]")) {
    // stuff happens here
}

It now needs to also be split by any operator which is stored in a variable called ops.

private String[] ops = {"+", "-", "*", "/", "%", "^"};

I'd like to keep it referencing ops, otherwise if I change something there, I have to remember to change it in this string split part too.

How can I just add this to the expression so that it reads 'split by whitespace or any one of these ops'?

e.g. userInput.split("[\\s+]|[ops]")

Extra info:

I am new to Java

JDK Amazon Corretto 11

IntelliJ IDEA CE 2019.3.2

答:
You could build a String by joining the array and then pass it to your regular expression (+|-|*|/|%|^), the only problem is that you are using some characters that have special meaning in regular expression (like * - Kleene star) and these should be escaped, whereas others should not.

To keep control ofm this, you can map each character you want to split the string by to the regular (part of) expression that should be used:

```<code>public static final Map<Character, String> opsToRegularExpression = Map.of(
        '+', "\\+",
        '-', "-",
        '*', "\\*",
        '/', "/",
        '%', "%",
        '^', "\\^"
);

public static final String regexpString =
        String.format("\\n+|\\s+|%s", String.join("|", opsToRegularExpression.values()));

// ...

for (String inputSplit : userInput.split(regexpString)) { }
</code>```

Body:
You could build a String by joining the array and then pass it to your regular expression (+|-|*|/|%|^), the only problem is that you are using some characters that have special meaning in regular expression (like * - Kleene star) and these should be escaped, whereas others should not.

To keep control ofm this, you can map each character you want to split the string by to the regular (part of) expression that should be used:

public static final Map<Character, String> opsToRegularExpression = Map.of(
        '+', "\\+",
        '-', "-",
        '*', "\\*",
        '/', "/",
        '%', "%",
        '^', "\\^"
);

public static final String regexpString =
        String.format("\\n+|\\s+|%s", String.join("|", opsToRegularExpression.values()));

// ...

for (String inputSplit : userInput.split(regexpString)) { }


问:
AngularJs -- Access to XMLHttpRequest has been blocked by CORS policy
error :

Access to XMLHttpRequest at 'http://localhost:8080/api/v1/locations' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I test the get method in a request.http file of WebStorm and in Postman and that work , but that doesn't work in my Angularjs project .
(I get from a Spring boot java project).

```<code>var app = angular.module('myApp', []);
  app.controller('myCtrl', function($scope, $http) {
    $http.get("http://localhost:8080/api/v1/locations")
            .then(function(response) {
              $scope.result = response.data;
              console.log("OK:", response.data);
            }).catch(function(response) {
              console.log("ERROR:", response);
    });
  });
</code>```

my get function return something like this in postman

```<code>[
 {
   "datetime": "2019-01-10T19:00:00.000+0000",
"user": {
  "firstName": "thr",
  "lastName": "an",
  "id": 1
},
"speed": 0.0,
"latitude": 37.421998333333335,
"longitude": -122.08400000000002,
"id": 1
},

{
   "datetime": "2019-01-10T19:01:00.000+0000",
"user": {
  "firstName": "thr",
  "lastName": "an",
  "id": 1
},
"speed": 1.575,
"latitude": 37.42198333333335,
"longitude": -122.080000000002,
"id": 2
}
]
</code>```

the console : https://i.top4top.io/p_1507d02621.jpg

答:
Add a .catch block to log errors:

```<code>var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
    $http.get("http://localhost:8080/api/v1/locations")
      .then(function(response) {
        $scope.result = response.data;
        console.log("OK:", response.data);
    }).catch(function(response) {
        console.log("ERROR:", response);
    });
});
</code>```

Body:
error :

Access to XMLHttpRequest at 'http://localhost:8080/api/v1/locations' from origin 'http://localhost:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I test the get method in a request.http file of WebStorm and in Postman and that work , but that doesn't work in my Angularjs project .
(I get from a Spring boot java project).

var app = angular.module('myApp', []);
  app.controller('myCtrl', function($scope, $http) {
    $http.get("http://localhost:8080/api/v1/locations")
            .then(function(response) {
              $scope.result = response.data;
              console.log("OK:", response.data);
            }).catch(function(response) {
              console.log("ERROR:", response);
    });
  });

my get function return something like this in postman

[
 {
   "datetime": "2019-01-10T19:00:00.000+0000",
"user": {
  "firstName": "thr",
  "lastName": "an",
  "id": 1
},
"speed": 0.0,
"latitude": 37.421998333333335,
"longitude": -122.08400000000002,
"id": 1
},

{
   "datetime": "2019-01-10T19:01:00.000+0000",
"user": {
  "firstName": "thr",
  "lastName": "an",
  "id": 1
},
"speed": 1.575,
"latitude": 37.42198333333335,
"longitude": -122.080000000002,
"id": 2
}
]

the console : https://i.top4top.io/p_1507d02621.jpg

Body:
Add a .catch block to log errors:

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
    $http.get("http://localhost:8080/api/v1/locations")
      .then(function(response) {
        $scope.result = response.data;
        console.log("OK:", response.data);
    }).catch(function(response) {
        console.log("ERROR:", response);
    });
});


问:
Class static variables reset when I call them in other file
I am practicing PHP, and the issue I encountered today is my static variable getting reset every time I call it.

Login Page after verfied user from DB

```<code><?php
Session::onlogin(1);
?>
</code>```

This is my session class it has a func onlogin and I send some data to it from another file which change $is_signed to true. But the issue is variable $is_signed getting reset when I call it from index.php it returns false

```<code><?php
class Session {

private static $is_signed = false;

function __construct(){
    session_start();
}

public static function is_signed_in(){
    return self::$is_signed;
}

public static function onLogin($userid){
    if($userid){
        session_regenerate_id();
        $_SESSION['user_id'] = $userid;
        self::$is_signed = true;
        return true;
    }
}
}
$session = new Session;
?>
</code>```

Now I am calling it in index.php as below

```<code>if(Session::is_signed_in()){
    echo "logged In";
}
else {
echo "error";
?>
</code>```

I don't know where I am creating any error but when I call the methods.

答:
So i asume this

class.php

```<code>class Session
{

    private static $is_signed = false;

    function __construct()
    {
        session_start();
    }

    public static function is_signed_in()
    {
        return self::$is_signed;
    }

    public static function onLogin($userid)
    {
        if ($userid) {
            session_regenerate_id();
            $_SESSION['user_id'] = $userid;
            self::$is_signed = true;
            return true;
        }
    }
}
$session = new Session;

</code>```

login.php

```<code><?php

require 'class.php';
$session = new Session;
Session::onlogin(1);
var_dump(Session::is_signed_in());// output true
</code>```

index.php

```<code><?php declare(strict_types = 1);
require 'class.php';

var_dump(Session::is_signed_in());// output false
</code>```

think about it that login.php and index.php are 2 separate programs not aware one of each other.Thats why you try put SESSION there change

```<code>    function __construct()
    {
        session_start();
        if (isset($_SESSION['user_id'])){
            self::$is_signed = true;
        }
    }
</code>```

and you are done

Body:
I am practicing PHP, and the issue I encountered today is my static variable getting reset every time I call it.

Login Page after verfied user from DB

<?php
Session::onlogin(1);
?>

This is my session class it has a func onlogin and I send some data to it from another file which change $is_signed to true. But the issue is variable $is_signed getting reset when I call it from index.php it returns false

<?php
class Session {

private static $is_signed = false;

function __construct(){
    session_start();
}

public static function is_signed_in(){
    return self::$is_signed;
}

public static function onLogin($userid){
    if($userid){
        session_regenerate_id();
        $_SESSION['user_id'] = $userid;
        self::$is_signed = true;
        return true;
    }
}
}
$session = new Session;
?>

Now I am calling it in index.php as below

if(Session::is_signed_in()){
    echo "logged In";
}
else {
echo "error";
?>

I don't know where I am creating any error but when I call the methods.

Body:
So i asume this

class.php

class Session
{

    private static $is_signed = false;

    function __construct()
    {
        session_start();
    }

    public static function is_signed_in()
    {
        return self::$is_signed;
    }

    public static function onLogin($userid)
    {
        if ($userid) {
            session_regenerate_id();
            $_SESSION['user_id'] = $userid;
            self::$is_signed = true;
            return true;
        }
    }
}
$session = new Session;

login.php

<?php

require 'class.php';
$session = new Session;
Session::onlogin(1);
var_dump(Session::is_signed_in());// output true

index.php

<?php declare(strict_types = 1);
require 'class.php';

var_dump(Session::is_signed_in());// output false

think about it that login.php and index.php are 2 separate programs not aware one of each other.Thats why you try put SESSION there change

    function __construct()
    {
        session_start();
        if (isset($_SESSION['user_id'])){
            self::$is_signed = true;
        }
    }

and you are done


问:
How to add an observable property when other properties change
I have the following model object that I use to populate a List with a Toggle for each row, which is bound to measurement.isSelected

```<code>final class Model: ObservableObject {

    struct Measurement: Identifiable {
        var id = UUID()
        let name: String
        var isSelected: Binding<Bool>

        var selected: Bool = false

        init(name: String) {
            self.name = name

            let selected = CurrentValueSubject<Bool, Never>(false)
            self.isSelected = Binding<Bool>(get: { selected.value }, set: { selected.value = $0 })
        }
    }

    @Published var measurements: [Measurement]
    @Published var hasSelection: Bool = false  // How to set this?

    init(measurements: [Measurement]) {
        self.measurements = measurements
    }
}
</code>```

I'd like the hasSelection property to be true whenever any measurement.isSelected is true. I'm guessing somehow Model needs to observe changes in measurements and then update its hasSelection property… but I've no idea where to start!

The idea is that hasSelection will be bound to a Button to enable or disable it.

Model is used as follows…

```<code>struct MeasurementsView: View {

    @ObservedObject var model: Model

    var body: some View {
        NavigationView {
            List(model.measurements) { measurement in
                MeasurementView(measurement: measurement)
            }
            .navigationBarTitle("Select Measurements")
            .navigationBarItems(trailing: NavigationLink(destination: NextView(), isActive: $model.hasSelection, label: {
                Text("Next")
            }))
        }
    }
}

struct MeasurementView: View {
    let measurement: Model.Measurement
    var body: some View {
        HStack {
            Text(measurement.name)
                .font(.subheadline)
            Spacer()
            Toggle(measurement.name, isOn: measurement.isSelected)
                .labelsHidden()
        }
    }
}
</code>```

For info, here's a screenshot of what I'm trying to achieve. A list of selectable items, with a navigation link that is enabled when one or more is selected, and disabled when no items are selected.

答:
The problem with your code at the moment is that even if you observe the changes to measurements, they will not get updated when the selection updates, because you declared the var isSelected: Binding<Bool> as a Binding. This means that SwiftUI is storing it outside of your struct, and the struct itself doesn't update (stays immutable).

What you could try instead is declaring @Published var selectedMeasurementId: UUID? = nil on your model So your code would be something like this:

import SwiftUI
import Combine

struct NextView: View {
    var body: some View {
        Text("Next View")

    }
}

struct MeasurementsView: View {

    @ObservedObject var model: Model

    var body: some View {

        let hasSelection = Binding<Bool> (
            get: {
                self.model.selectedMeasurementId != nil
            },
            set: { value in
                self.model.selectedMeasurementId = nil
            }
        )

        return NavigationView {
            List(model.measurements) { measurement in
                MeasurementView(measurement: measurement, selectedMeasurementId: self.$model.selectedMeasurementId)
            }
            .navigationBarTitle("Select Measurements")
            .navigationBarItems(trailing: NavigationLink(destination: NextView(), isActive: hasSelection, label: {
                Text("Next")
            }))
        }
    }
}

struct MeasurementView: View {

    let measurement: Model.Measurement
    @Binding var selectedMeasurementId: UUID?

    var body: some View {

        let isSelected = Binding<Bool>(
            get: {
                self.selectedMeasurementId == self.measurement.id
            },
            set: { value in
                if value {
                    self.selectedMeasurementId = self.measurement.id
                } else {
                    self.selectedMeasurementId = nil
                }
            }
        )

        return HStack {
            Text(measurement.name)
                .font(.subheadline)
            Spacer()
            Toggle(measurement.name, isOn: isSelected)
                .labelsHidden()
        }
    }
}

final class Model: ObservableObject {

    @Published var selectedMeasurementId: UUID? = nil

    struct Measurement: Identifiable {
        var id = UUID()
        let name: String

        init(name: String) {
            self.name = name
        }
    }

    @Published var measurements: [Measurement]

    init(measurements: [Measurement]) {
        self.measurements = measurements
    }
}

```

I'm not sure exactly how you want the navigation button in the navbar to behave. For now I just set the selection to nil when it's tapped. You can modify it depending on what you want to do.

If you want to support multi-selection, you can use a Set of selected ids instead.

Also, seems like the iOS simulator has some problems with navigation, but I tested on a physical device and it worked.

Body:
I have the following model object that I use to populate a List with a Toggle for each row, which is bound to measurement.isSelected

final class Model: ObservableObject {

    struct Measurement: Identifiable {
        var id = UUID()
        let name: String
        var isSelected: Binding<Bool>

        var selected: Bool = false

        init(name: String) {
            self.name = name

            let selected = CurrentValueSubject<Bool, Never>(false)
            self.isSelected = Binding<Bool>(get: { selected.value }, set: { selected.value = $0 })
        }
    }

    @Published var measurements: [Measurement]
    @Published var hasSelection: Bool = false  // How to set this?

    init(measurements: [Measurement]) {
        self.measurements = measurements
    }
}

I'd like the hasSelection property to be true whenever any measurement.isSelected is true. I'm guessing somehow Model needs to observe changes in measurements and then update its hasSelection property… but I've no idea where to start!

The idea is that hasSelection will be bound to a Button to enable or disable it.

Model is used as follows…

struct MeasurementsView: View {

    @ObservedObject var model: Model

    var body: some View {
        NavigationView {
            List(model.measurements) { measurement in
                MeasurementView(measurement: measurement)
            }
            .navigationBarTitle("Select Measurements")
            .navigationBarItems(trailing: NavigationLink(destination: NextView(), isActive: $model.hasSelection, label: {
                Text("Next")
            }))
        }
    }
}

struct MeasurementView: View {
    let measurement: Model.Measurement
    var body: some View {
        HStack {
            Text(measurement.name)
                .font(.subheadline)
            Spacer()
            Toggle(measurement.name, isOn: measurement.isSelected)
                .labelsHidden()
        }
    }
}

For info, here's a screenshot of what I'm trying to achieve. A list of selectable items, with a navigation link that is enabled when one or more is selected, and disabled when no items are selected.

Body:
The problem with your code at the moment is that even if you observe the changes to measurements, they will not get updated when the selection updates, because you declared the var isSelected: Binding<Bool> as a Binding. This means that SwiftUI is storing it outside of your struct, and the struct itself doesn't update (stays immutable).

What you could try instead is declaring @Published var selectedMeasurementId: UUID? = nil on your model So your code would be something like this:

import SwiftUI
import Combine

struct NextView: View {
    var body: some View {
        Text("Next View")

    }
}

struct MeasurementsView: View {

    @ObservedObject var model: Model

    var body: some View {

        let hasSelection = Binding<Bool> (
            get: {
                self.model.selectedMeasurementId != nil
            },
            set: { value in
                self.model.selectedMeasurementId = nil
            }
        )

        return NavigationView {
            List(model.measurements) { measurement in
                MeasurementView(measurement: measurement, selectedMeasurementId: self.$model.selectedMeasurementId)
            }
            .navigationBarTitle("Select Measurements")
            .navigationBarItems(trailing: NavigationLink(destination: NextView(), isActive: hasSelection, label: {
                Text("Next")
            }))
        }
    }
}

struct MeasurementView: View {

    let measurement: Model.Measurement
    @Binding var selectedMeasurementId: UUID?

    var body: some View {

        let isSelected = Binding<Bool>(
            get: {
                self.selectedMeasurementId == self.measurement.id
            },
            set: { value in
                if value {
                    self.selectedMeasurementId = self.measurement.id
                } else {
                    self.selectedMeasurementId = nil
                }
            }
        )

        return HStack {
            Text(measurement.name)
                .font(.subheadline)
            Spacer()
            Toggle(measurement.name, isOn: isSelected)
                .labelsHidden()
        }
    }
}

final class Model: ObservableObject {

    @Published var selectedMeasurementId: UUID? = nil

    struct Measurement: Identifiable {
        var id = UUID()
        let name: String

        init(name: String) {
            self.name = name
        }
    }

    @Published var measurements: [Measurement]

    init(measurements: [Measurement]) {
        self.measurements = measurements
    }
}

I'm not sure exactly how you want the navigation button in the navbar to behave. For now I just set the selection to nil when it's tapped. You can modify it depending on what you want to do.

If you want to support multi-selection, you can use a Set of selected ids instead.

Also, seems like the iOS simulator has some problems with navigation, but I tested on a physical device and it worked.


问:
Android 2D game programming: using OpenGL or not?
I've just started to develop games on Android. My first game is a 2D game and I'm wondering whether I should use OpenGL or not.

Does anyone have some advice on this?

Thanks a lot,
Viet

答: You will want to use OpenGL ES if you want anything close to a respectable frame rate. OpenGL ES is hardware accelerated (uses the GPU), while other libraries mostly use the CPU.</p>


问:
How to get User ID or GUID from BMC Remedy User using Java
I am using the Remedy API for Java.
How do I get a User ID or the User GUID from a Remedy User using java?

I do a simple logon using something like the following:

```<code>ARServerUser sUser = new ARServerUser("server", "port", "user", "pass", 1);
</code>```

The sUser object however does not have any userid or guid inside it?
I have looked at the API and cannot find a method to retrieve it. I have also tried looking in the UserInfo object, but that also doe not contain it?

Any ideas?
Thanks

答:
Sample code to fetch ALL details for a User.

```<code>ARServerUser arConnection = new ARServerUser("server", "port", "user", "pass", 1);

List<SortInfo> sortList = new ArrayList<SortInfo>();
int firstRetreive = 0;
int maxRetreive = maxNumEntries;//1M
OutputInteger numMatches = new OutputInteger();
ResultEntryList iterator = new ResultEntryList(data);
QualifierInfo qiPlain = new QualifierInfo();

//make field list for results
List<Field> fields = arConnection.getListFieldObjects(formName);
ArrayList<Integer> alFieldIds = new ArrayList<Integer>();
for (int x = 0; x <
   fields.size(); x++) {
   alFieldIds.add(fields.get(x).getFieldID());
}
int[] fieldIds = new int[alFieldIds.size()];
for (int i = 0; i < fieldIds.length; i++) {
  fieldIds[i] = ((Integer) alFieldIds.get(i)).intValue();
}
arConnection.getListEntryObjects("User", qiPlain, firstRetreive, maxRetreive, sortList, fieldIds, false, numMatches, iterator);
</code>```

If you just want the ids, you can skip the retrieval of all the field IDs. unfortunately I cannot remember the ID of the username field. Substitute the xxx with its  ID)

```<code>ARServerUser arConnection = new ARServerUser("server", "port", "user", "pass", 1);

List<SortInfo> sortList = new ArrayList<SortInfo>();
int firstRetreive = 0;
int maxRetreive = maxNumEntries;//1M
OutputInteger numMatches = new OutputInteger();
ResultEntryList iterator = new ResultEntryList(data);
QualifierInfo qiPlain = new QualifierInfo();

//make field list for results
int[] fieldIds = {Constants.AR_CORE_ENTRY_ID, xxx};

arConnection.getListEntryObjects("User", qiPlain, firstRetreive, maxRetreive, sortList, fieldIds, false, numMatches, iterator);
</code>```

Body:
I am using the Remedy API for Java.
How do I get a User ID or the User GUID from a Remedy User using java?

I do a simple logon using something like the following:

ARServerUser sUser = new ARServerUser("server", "port", "user", "pass", 1);

The sUser object however does not have any userid or guid inside it?
I have looked at the API and cannot find a method to retrieve it. I have also tried looking in the UserInfo object, but that also doe not contain it?

Any ideas?
Thanks

Body:
Sample code to fetch ALL details for a User.

ARServerUser arConnection = new ARServerUser("server", "port", "user", "pass", 1);

List<SortInfo> sortList = new ArrayList<SortInfo>();
int firstRetreive = 0;
int maxRetreive = maxNumEntries;//1M
OutputInteger numMatches = new OutputInteger();
ResultEntryList iterator = new ResultEntryList(data);
QualifierInfo qiPlain = new QualifierInfo();

//make field list for results
List<Field> fields = arConnection.getListFieldObjects(formName);
ArrayList<Integer> alFieldIds = new ArrayList<Integer>();
for (int x = 0; x <
   fields.size(); x++) {
   alFieldIds.add(fields.get(x).getFieldID());
}
int[] fieldIds = new int[alFieldIds.size()];
for (int i = 0; i < fieldIds.length; i++) {
  fieldIds[i] = ((Integer) alFieldIds.get(i)).intValue();
}
arConnection.getListEntryObjects("User", qiPlain, firstRetreive, maxRetreive, sortList, fieldIds, false, numMatches, iterator);

If you just want the ids, you can skip the retrieval of all the field IDs. unfortunately I cannot remember the ID of the username field. Substitute the xxx with its  ID)

ARServerUser arConnection = new ARServerUser("server", "port", "user", "pass", 1);

List<SortInfo> sortList = new ArrayList<SortInfo>();
int firstRetreive = 0;
int maxRetreive = maxNumEntries;//1M
OutputInteger numMatches = new OutputInteger();
ResultEntryList iterator = new ResultEntryList(data);
QualifierInfo qiPlain = new QualifierInfo();

//make field list for results
int[] fieldIds = {Constants.AR_CORE_ENTRY_ID, xxx};

arConnection.getListEntryObjects("User", qiPlain, firstRetreive, maxRetreive, sortList, fieldIds, false, numMatches, iterator);


答:
First of all you can construct regular expression, then use it in order to separate how you want.</p>

```<code>public class Main {
    public static void main(String[] args) {
        String[] ops = {"+", "-", "*", "/", "%", "^"};
        String separators = "\\s";

        String userInput = "QWE QWSDF DSFDG DFG GSFH GDSG DSFG DSF+6561 AS/DAS 654654 132-6564 ASD*ASD DFGD^FGF";

        for (String separator : ops) {
            separators += "\\" + separator;
        }

        for (String inputSplit : userInput.split("[" + separators + "]")) {
            System.out.println(inputSplit);
        }
    }
}
</code>```

Title: Java String Split by \\s+ and by String Array

Body:
In this code a user will input some text. It then needs to be split by whitespace - I am currently using:

for (String inputSplit : userInput.split("[\\s+]")) {
    // stuff happens here
}

It now needs to also be split by any operator which is stored in a variable called ops.

private String[] ops = {"+", "-", "*", "/", "%", "^"};

I'd like to keep it referencing ops, otherwise if I change something there, I have to remember to change it in this string split part too.

How can I just add this to the expression so that it reads 'split by whitespace or any one of these ops'?

e.g. userInput.split("[\\s+]|[ops]")

Extra info:

I am new to Java

JDK Amazon Corretto 11

IntelliJ IDEA CE 2019.3.2

Body:
First of all you can construct regular expression, then use it in order to separate how you want.

public class Main {
    public static void main(String[] args) {
        String[] ops = {"+", "-", "*", "/", "%", "^"};
        String separators = "\\s";

        String userInput = "QWE QWSDF DSFDG DFG GSFH GDSG DSFG DSF+6561 AS/DAS 654654 132-6564 ASD*ASD DFGD^FGF";

        for (String separator : ops) {
            separators += "\\" + separator;
        }

        for (String inputSplit : userInput.split("[" + separators + "]")) {
            System.out.println(inputSplit);
        }
    }
}


问:
calculate average for group based on element value
I have a table with 2 columns: Model and Price

```<code>Model       Price
Pilot       30
Civic       20
Highlander  10
Corolla     40
Rav4        25
</code>```

I know that Pilot and Civic is Honda car while Highlander, Corolla, Rav4 is Toyota.
I want to calculate, say average price for Honda group (30+20)/2 and Toyota (10+40+25)/3.

Output table:

```<code>Mode    Average_price
Honda   25
Toyota  25
</code>```

My problem is that I am NOT allowed to create new table or new column in existing table.

Thus I think somewhere in the query I need to list all condition say

```<code>IF Model in ('Pilot','Civic') then Manufacturer='Honda' else if Model in ('Highlander','Corolla','Rav4') then Manufacturer='Toyota'
Then average by Manufacturer.
</code>```

Can anyone please help me to write a query?

Thank you,

Harry

答:
You can use a case expression:

```<code>select
    case
        when model in ('Pilot', 'Civic') then 'Honda'
        when model in ('Highlander', 'Corolla', 'Rav4') then 'Toyota'
    end mode,
    avg(price) avg_price
from mytable
group by
    case
        when model in ('Pilot', 'Civic') then 'Honda'
        when model in ('Highlander', 'Corolla', 'Rav4') then 'Toyota'
    end
</code>```

Some databases extend the SQL standard by allowing the use of aliases in the group by clause (eg MySQL), so you can simplify it as follows:

```<code>group by mode
</code>```

Body:
I have a table with 2 columns: Model and Price

Model       Price
Pilot       30
Civic       20
Highlander  10
Corolla     40
Rav4        25

I know that Pilot and Civic is Honda car while Highlander, Corolla, Rav4 is Toyota.
I want to calculate, say average price for Honda group (30+20)/2 and Toyota (10+40+25)/3.

Output table:

Mode    Average_price
Honda   25
Toyota  25

My problem is that I am NOT allowed to create new table or new column in existing table.

Thus I think somewhere in the query I need to list all condition say

IF Model in ('Pilot','Civic') then Manufacturer='Honda' else if Model in ('Highlander','Corolla','Rav4') then Manufacturer='Toyota'
Then average by Manufacturer.

Can anyone please help me to write a query?

Thank you,

Harry

Body:
You can use a case expression:

select
    case
        when model in ('Pilot', 'Civic') then 'Honda'
        when model in ('Highlander', 'Corolla', 'Rav4') then 'Toyota'
    end mode,
    avg(price) avg_price
from mytable
group by
    case
        when model in ('Pilot', 'Civic') then 'Honda'
        when model in ('Highlander', 'Corolla', 'Rav4') then 'Toyota'
    end

Some databases extend the SQL standard by allowing the use of aliases in the group by clause (eg MySQL), so you can simplify it as follows:

group by mode


问:
Merge dataframes within an ordered list
I had a dictionary of dataframes (opdict) that I sorted according to its key values. This gave me a list of tuples (oplist), with the tuples containing two elements: Index 0 with key values of opdict and Index 1 with the values (dataframes) of opdict. My question is, how do I merge all the dataframes within oplist to a single dataframe (opdf) row by row i.e. first stack together all the first rows of all dataframes within oplist, then stack together all the second rows of all dataframes within oplist and so on. I have a feeling that pandas.concat or pandas.join is the way to go, but I am not sure of the correct code. Thanks for your help!

答:
List of tuples to list of DataFrames:

```<code>list_of_dfs = [i[1] for i in oplist]
</code>```

Concatenate, then sort by the index:

```<code>concat_df = pd.concat(list_of_dfs).sort_index()
</code>```

Title: Merge dataframes within an ordered list

Body:
List of tuples to list of DataFrames:

list_of_dfs = [i[1] for i in oplist]

Concatenate, then sort by the index:

concat_df = pd.concat(list_of_dfs).sort_index()


答: As far as I know OpenGL ES will give better performance (especially on Tegra 2 devices). OpenGL ES is also harder to learn, but there are good tutorials and support libraries. </p>

Title: Android 2D game programming: using OpenGL or not?

Body:
I've just started to develop games on Android. My first game is a 2D game and I'm wondering whether I should use OpenGL or not.

Does anyone have some advice on this?

Thanks a lot,
Viet


问:
Return most often present string in list
I would like to return the text most often present in a list, for return in method

My list = ((EPlayersStats)x.Value).kList

Json = "kList": ["76561198130200574,16561198130200574,26561198130200574,36561198130200574,76561198130200574"]

How do I proceed?

答:
Could do it with LINQ grouping:

```<code>myList.Split(',').GroupBy(s => s).OrderByDescending(g => g.Count()).First().Key
</code>```

This splits on comma, turns the lot into a grouping (a mapping of each unique entry mapped to a list of all the occurrences of that entry), sorts by the number of entries in the grouping list, takes the first grouping and returns its key

```<code>A list of: "a,b,b,c,d,d,d"
Becomes an array: { "a", "b", "b", "c", "d", "d", "d" }
Becomes a grouping:
  g["a"] = new [] { "a" } //Count 1
  g["b"] = new [] { "b", "b" } //count 2
  g["c"] = new [] { "c" } //count 1
  g["d"] = new [] { "d", "d", "d" } //count 3
Orders them by count desc (d wins)
Takes the first grouping (d)
Returns its Key ("d")
</code>```

Body:
Could do it with LINQ grouping:

myList.Split(',').GroupBy(s => s).OrderByDescending(g => g.Count()).First().Key

This splits on comma, turns the lot into a grouping (a mapping of each unique entry mapped to a list of all the occurrences of that entry), sorts by the number of entries in the grouping list, takes the first grouping and returns its key

A list of: "a,b,b,c,d,d,d"
Becomes an array: { "a", "b", "b", "c", "d", "d", "d" }
Becomes a grouping:
  g["a"] = new [] { "a" } //Count 1
  g["b"] = new [] { "b", "b" } //count 2
  g["c"] = new [] { "c" } //count 1
  g["d"] = new [] { "d", "d", "d" } //count 3
Orders them by count desc (d wins)
Takes the first grouping (d)
Returns its Key ("d")


问:
Index JSON in SQLAlchemy on Postgresql
I am using JSON in my SQLAlchemy DB model:

```<code>from sqlalchemy.dialects.postgresql import JSON

class Customer(db.Model):
  id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  custcontext_json = db.Column(JSON, default=lambda: {})
</code>```

Now I have this query that is getting too slow:

```<code>customers = Customer.query.filter(
  Customer.clientid == clientid,
  or_(
    func.lower(Customer.custcontext_json['cinfo', 'userName'].astext.cast(Unicode)).contains(searchterm.lower()),
    func.lower(Customer.custcontext_json['cinfo', 'home', 'sign'].astext.cast(Unicode)).contains(searchterm.lower())
  ),

  or_(
    Customer.custcontext_json['cinfo', 'home', 'status'].astext == 'pre',
    Customer.custcontext_json['cinfo', 'home', 'status'].astext == 'during',
    Customer.custcontext_json['cinfo', 'lastChange'].astext.cast(DateTime) > pendulum.now('UTC').subtract(days=14)
  )
  ).all()
</code>```

Is it possible to index the table for this query. Or at least parts of it?

答:
I would use JSONB as format with higher density. But that is not an answer.

Please look here. Operators for JSON type in PostgreSQL, you can get from here. I would like to get your create table, to reproduce something at my side. Any way. I would start with something like this:

```<code>create table customer (clientid serial, custcontext_json jsonb);

create index on customer (
  (CAST((custcontext_json->'cinfo'->'userName') AS TEXT)),
  (CAST((custcontext_json->'cinfo'->'home'->'sign') AS TEXT)),
  (CAST((custcontext_json->'cinfo'->'home'->'status') AS TEXT)));
</code>```

Title: Index JSON in SQLAlchemy on Postgresql

Body:
I am using JSON in my SQLAlchemy DB model:

from sqlalchemy.dialects.postgresql import JSON

class Customer(db.Model):
  id = db.Column(db.Integer, primary_key=True, autoincrement=True)
  custcontext_json = db.Column(JSON, default=lambda: {})

Now I have this query that is getting too slow:

customers = Customer.query.filter(
  Customer.clientid == clientid,
  or_(
    func.lower(Customer.custcontext_json['cinfo', 'userName'].astext.cast(Unicode)).contains(searchterm.lower()),
    func.lower(Customer.custcontext_json['cinfo', 'home', 'sign'].astext.cast(Unicode)).contains(searchterm.lower())
  ),

  or_(
    Customer.custcontext_json['cinfo', 'home', 'status'].astext == 'pre',
    Customer.custcontext_json['cinfo', 'home', 'status'].astext == 'during',
    Customer.custcontext_json['cinfo', 'lastChange'].astext.cast(DateTime) > pendulum.now('UTC').subtract(days=14)
  )
  ).all()

Is it possible to index the table for this query. Or at least parts of it?

Body:
I would use JSONB as format with higher density. But that is not an answer.

Please look here. Operators for JSON type in PostgreSQL, you can get from here. I would like to get your create table, to reproduce something at my side. Any way. I would start with something like this:

create table customer (clientid serial, custcontext_json jsonb);

create index on customer (
  (CAST((custcontext_json->'cinfo'->'userName') AS TEXT)),
  (CAST((custcontext_json->'cinfo'->'home'->'sign') AS TEXT)),
  (CAST((custcontext_json->'cinfo'->'home'->'status') AS TEXT)));


问:
How can we animate a navigateUp() fragment transition?
When executing fragment transactions that are part of the androidx.navigation system, we can specify NavOptions programmatically like this:

```<code>val navOptions = NavOptions.Builder()
        .setEnterAnim(R.anim.slide_in_right)
        .build()
    findNavController(R.id.nav_host_fragment).navigate(R.id.settingsFragment, null, navOptions)
</code>```

We can also specify them in the navigation.xml like this:

```<code> <fragment
        android:id="@+id/settingsFragment"
        android:name="com.test.android.fragments.SettingsFragment"
        android:label="SettingsFragment">

        <action
            android:id="@+id/action_settings_to_profile"
            app:destination="@id/userProfileSettingsFragment"
            app:enterAnim="@anim/slide_in_right" />

</fragment>
</code>```

But how can we animate the navigateUp() method?   It doesn't accept NavOptions.   I am sliding from right my fragment, but when the user presses Back, there's no animation taking place.  I want to do a slide to right animation (the reverse of the one they saw when getting there).

How can I animate:   navigateUp() ?     It calls popBackStackInternal internally which is a complicated operation.  I don't see any logic having to do with animation there.

Any alternative solutions to returning to where you came from with animation, besides navigateUp() ?

答:
You can use the popEnterAnim and popExitAnim attributes like this:

 <fragment
    android:id="@+id/settingsFragment"
    android:name="com.storefaces.android.fragments.SettingsFragment"
    android:label="SettingsFragment">

    <action
        android:id="@+id/action_settings_to_profile"
        app:destination="@id/userProfileSettingsFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_right"
        app:popEnterAnim="@anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_left" />

</fragment>
```

<p>Alternatively, you can call <code>setPopEnterAnim()</code> and <code>setPopExitAnim()</code> methods on <code>NavOptions.Builder</code></p>

```val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_right)
    .setPopEnterAnim(R.anim.slide_in_left)
    .setPopExitAnim(R.anim.slide_out_left)
    .build()

findNavController(R.id.nav_host_fragment).navigate(R.id.settingsFragment, null, navOptions)
```

Body:
When executing fragment transactions that are part of the androidx.navigation system, we can specify NavOptions programmatically like this:

val navOptions = NavOptions.Builder()
        .setEnterAnim(R.anim.slide_in_right)
        .build()
    findNavController(R.id.nav_host_fragment).navigate(R.id.settingsFragment, null, navOptions)

We can also specify them in the navigation.xml like this:

 <fragment
        android:id="@+id/settingsFragment"
        android:name="com.test.android.fragments.SettingsFragment"
        android:label="SettingsFragment">

        <action
            android:id="@+id/action_settings_to_profile"
            app:destination="@id/userProfileSettingsFragment"
            app:enterAnim="@anim/slide_in_right" />

</fragment>

But how can we animate the navigateUp() method?   It doesn't accept NavOptions.   I am sliding from right my fragment, but when the user presses Back, there's no animation taking place.  I want to do a slide to right animation (the reverse of the one they saw when getting there).

How can I animate:   navigateUp() ?     It calls popBackStackInternal internally which is a complicated operation.  I don't see any logic having to do with animation there.

Any alternative solutions to returning to where you came from with animation, besides navigateUp() ?

Body:
You can use the popEnterAnim and popExitAnim attributes like this:

 <fragment
    android:id="@+id/settingsFragment"
    android:name="com.storefaces.android.fragments.SettingsFragment"
    android:label="SettingsFragment">

    <action
        android:id="@+id/action_settings_to_profile"
        app:destination="@id/userProfileSettingsFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_right"
        app:popEnterAnim="@anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_left" />

</fragment>

Alternatively, you can call setPopEnterAnim() and setPopExitAnim() methods on NavOptions.Builder

val navOptions = NavOptions.Builder()
    .setEnterAnim(R.anim.slide_in_right)
    .setExitAnim(R.anim.slide_out_right)
    .setPopEnterAnim(R.anim.slide_in_left)
    .setPopExitAnim(R.anim.slide_out_left)
    .build()

findNavController(R.id.nav_host_fragment).navigate(R.id.settingsFragment, null, navOptions)


问:
How to retry after sql connection failed in python?
Whats the right way to retry when connection/write to a DB fails in python?

Im trying to use this code and it works until i restart my sql server and python tries to connect to it i get "retry after 30 sec" for 10 times with 30 secs intervalls but it wont reconnect when sql server is running agian.

EDIT: It reconnects when retry_count1 = 10 but at next cycle counter needs to count up to 10 before it connects agian.

Does anyone have a idea why it wont reconnect?

```<code> retry_flag1 = True
        retry_count1 = 0
        while retry_flag1 and retry_count1 < 10:
          try:
            cursor = cnxn.cursor()
            cursor.execute('SELECT too_id FROM [TTMM].[dbo].[Machines] WHERE MachineID = {}'.format (machineid,))
            too_id = cursor.fetchone()[0]
            cursor.execute('INSERT INTO [TTMM].[dbo].[{}](counter, effectively, too_id) VALUES ({},{},{})'.format (machineid, counter, effectively, too_id,))
            cnxn.commit()
            cursor.close()
            retry_flag1 = False
          except as e:
            print(e)
            print("Retry after 30 sec")
            retry_count1 = retry_count1 + 1
            time.sleep(30)
</code>```

Heres console output after restarting sql server.

```<code>('08S01', '[08S01] [FreeTDS][SQL Server]Write to the server failed (20006) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
141222 Cykel
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
</code>```

答:
I found a solution by adding cnxn.close and create a new connection.</p>

```<code>    retry_flag = True
    retry_count = 0
    cursor = cnxn.cursor()
    while retry_flag and retry_count < 5:
        try:
            cursor.execute('SELECT too_id FROM [TTMM].[dbo].[Machines] WHERE MachineID = {}'.format (machineid,))
            too_id = cursor.fetchone()[0]
            cursor.execute('INSERT INTO [TTMM].[dbo].[{}](counter, effectively, too_id) VALUES ({},{},{})'.format (machineid, counter, effectively, too_id,))
            retry_flag = False
            print("Printed To DB - Counter = ", counter, ", Effectively = ", effectively, ", too_id = ", too_id,)

        except Exception as e:
            print (e)
            print ("Retry after 5 sec")
            retry_count = retry_count + 1
            cursor.close()
            cnxn.close()
            time.sleep(5)
            cnxn = pyodbc.connect('DRIVER=FreeTDS;SERVER=*;PORT=*;DATABASE=*;UID=*;PWD=*;TDS_Version=8.7;', autocommit=True)
            cursor = cnxn.cursor()

    cursor.close()
</code>```

Body:
Whats the right way to retry when connection/write to a DB fails in python?

Im trying to use this code and it works until i restart my sql server and python tries to connect to it i get "retry after 30 sec" for 10 times with 30 secs intervalls but it wont reconnect when sql server is running agian.

EDIT: It reconnects when retry_count1 = 10 but at next cycle counter needs to count up to 10 before it connects agian.

Does anyone have a idea why it wont reconnect?

 retry_flag1 = True
        retry_count1 = 0
        while retry_flag1 and retry_count1 < 10:
          try:
            cursor = cnxn.cursor()
            cursor.execute('SELECT too_id FROM [TTMM].[dbo].[Machines] WHERE MachineID = {}'.format (machineid,))
            too_id = cursor.fetchone()[0]
            cursor.execute('INSERT INTO [TTMM].[dbo].[{}](counter, effectively, too_id) VALUES ({},{},{})'.format (machineid, counter, effectively, too_id,))
            cnxn.commit()
            cursor.close()
            retry_flag1 = False
          except as e:
            print(e)
            print("Retry after 30 sec")
            retry_count1 = retry_count1 + 1
            time.sleep(30)

Heres console output after restarting sql server.

('08S01', '[08S01] [FreeTDS][SQL Server]Write to the server failed (20006) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
141222 Cykel
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')
Retry after 1 sec
('08S01', '[08S01] [FreeTDS][SQL Server]Communication link failure (0) (SQLExecDirectW)')

Body:
I found a solution by adding cnxn.close and create a new connection.

    retry_flag = True
    retry_count = 0
    cursor = cnxn.cursor()
    while retry_flag and retry_count < 5:
        try:
            cursor.execute('SELECT too_id FROM [TTMM].[dbo].[Machines] WHERE MachineID = {}'.format (machineid,))
            too_id = cursor.fetchone()[0]
            cursor.execute('INSERT INTO [TTMM].[dbo].[{}](counter, effectively, too_id) VALUES ({},{},{})'.format (machineid, counter, effectively, too_id,))
            retry_flag = False
            print("Printed To DB - Counter = ", counter, ", Effectively = ", effectively, ", too_id = ", too_id,)

        except Exception as e:
            print (e)
            print ("Retry after 5 sec")
            retry_count = retry_count + 1
            cursor.close()
            cnxn.close()
            time.sleep(5)
            cnxn = pyodbc.connect('DRIVER=FreeTDS;SERVER=*;PORT=*;DATABASE=*;UID=*;PWD=*;TDS_Version=8.7;', autocommit=True)
            cursor = cnxn.cursor()

    cursor.close()


问:
Accessing the inner array of an associative array in PHP
I have created a very simple associative array of ids from a MySQL database.

Contents of the array look somewhat like this:

```<code>[0]=> array(1) { ["id"]=> int(2) }
[1]=> array(1) { ["id"]=> int(3) }
[2]=> array(1) { ["id"]=> int(4) }
[3]=> array(1) { ["id"]=> int(15) }
[4]=> array(1) { ["id"]=> int(17) }
[5]=> array(1) { ["id"]=> int(18) }
[6]=> array(1) { ["id"]=> int(3) } etc.
</code>```

However, for the purposes that I am using the array, I need to access the ID integers, so that they can be used to flag rows in the parent table.  However, the scripts that I have created do not seem to use the ["id"]=> int(2) and therefore the code fails.

The code that I have as follows:

MySQL code:

```<code>  public function unused()
    {
        $query = "select person.id from person, thing, person_thing
WHERE flag = 1 AND person.id = person_thing.person_id AND person_thing.thing_id = thing.id and thing.name != 'used'
AND person.name NOT IN (select person.name from person, thing, person_thing WHERE person.id = person_thing.person_id
AND person_thing.thing_id = thing.id and thing.name = 'used')";
        $stmt = $this->Conn->prepare($query);
        $stmt->execute(array());
        return
        $stmt->fetchAll(PDO::FETCH_ASSOC);
</code>```

Function code:

```<code>{
        $things = $thing->unused();
        $smarty->assign('thing_used', $things);
        for ($i = 0; $i <= count($things); $i++) {
            $gameView->iterateThings($things[$i]);
        }
</code>```

Iterate method code

```<code>Public function iterateThings($id)
    {
        $changeFlag = "UPDATE thingview SET flag = false WHERE  id= :id";
        $stmt = $this->Conn->prepare($changeFlag);
        $stmt->execute(array(':id' => $id));

    }
</code>```

I have a view called set up which has boolean flags all set to true.  I'm trying to use this code change the flag settings on all the person.ids that are in the associative array $things.  Naively, I thought that this would be enough, but every time I run the code, the flags remain unchanged.  It appears that the contents of the array is: array(1) { ["id"]=> int(2) } where what I need is { ["id"]=> int(2) }.  I need the index gone and just the array.  I have googled this ad infinitum but have been unsuccessful.  Any ideas?

答: I have realised that I have created a multidimensional array...  That was throwing me.  I believe at this point, more research is required on multidimensional arrays and should I need further help, I will rephrase the question.</p>

Body:
I have created a very simple associative array of ids from a MySQL database.

Contents of the array look somewhat like this:

[0]=> array(1) { ["id"]=> int(2) }
[1]=> array(1) { ["id"]=> int(3) }
[2]=> array(1) { ["id"]=> int(4) }
[3]=> array(1) { ["id"]=> int(15) }
[4]=> array(1) { ["id"]=> int(17) }
[5]=> array(1) { ["id"]=> int(18) }
[6]=> array(1) { ["id"]=> int(3) } etc.

However, for the purposes that I am using the array, I need to access the ID integers, so that they can be used to flag rows in the parent table.  However, the scripts that I have created do not seem to use the ["id"]=> int(2) and therefore the code fails.

The code that I have as follows:

MySQL code:

  public function unused()
    {
        $query = "select person.id from person, thing, person_thing
WHERE flag = 1 AND person.id = person_thing.person_id AND person_thing.thing_id = thing.id and thing.name != 'used'
AND person.name NOT IN (select person.name from person, thing, person_thing WHERE person.id = person_thing.person_id
AND person_thing.thing_id = thing.id and thing.name = 'used')";
        $stmt = $this->Conn->prepare($query);
        $stmt->execute(array());
        return
        $stmt->fetchAll(PDO::FETCH_ASSOC);

Function code:

{
        $things = $thing->unused();
        $smarty->assign('thing_used', $things);
        for ($i = 0; $i <= count($things); $i++) {
            $gameView->iterateThings($things[$i]);
        }

Iterate method code

Public function iterateThings($id)
    {
        $changeFlag = "UPDATE thingview SET flag = false WHERE  id= :id";
        $stmt = $this->Conn->prepare($changeFlag);
        $stmt->execute(array(':id' => $id));

    }

I have a view called set up which has boolean flags all set to true.  I'm trying to use this code change the flag settings on all the person.ids that are in the associative array $things.  Naively, I thought that this would be enough, but every time I run the code, the flags remain unchanged.  It appears that the contents of the array is: array(1) { ["id"]=> int(2) } where what I need is { ["id"]=> int(2) }.  I need the index gone and just the array.  I have googled this ad infinitum but have been unsuccessful.  Any ideas?


问:
Retrive value list of Decimal Type without class name
when I run this query in django:

```<code>list(InputDataDetailItem.objects.filter(wage_detail__wage=wage).values_list('value',flat=True))
</code>```

I get :

```<code>[Decimal('30.00'), Decimal('0.00'), Decimal('0.00')]
</code>```

but I want :

```<code>[30.00,0.00,0.00]

</code>```

How can I do this?
Thank you.

答:
That is because it is (likely) a DecimalField [Django-doc]. You can convert these by calling float on them:

```<code>[   <b>float(x)</b>
    for x in InputDataDetailItem.objects.filter(
        wage_detail__wage=wage
    ).values_list('value',flat=True)]</code>```

Note that since a Decimal encodes digits, whereas a float encodes binary, there might be (small) rounding errors.

Body:
when I run this query in django:

list(InputDataDetailItem.objects.filter(wage_detail__wage=wage).values_list('value',flat=True))

I get :

[Decimal('30.00'), Decimal('0.00'), Decimal('0.00')]

but I want :

[30.00,0.00,0.00]

How can I do this?
Thank you.

Body:
That is because it is (likely) a DecimalField [Django-doc]. You can convert these by calling float on them:

[   float(x)
    for x in InputDataDetailItem.objects.filter(
        wage_detail__wage=wage
    ).values_list('value',flat=True)]

Note that since a Decimal encodes digits, whereas a float encodes binary, there might be (small) rounding errors.


问:
How to set Textbox value at page load?
I have to set asp.net TextBox’s value at page load using JQuery.

Can somebody give me example ?

答:
You can use document.ready

Example http://fiddle.jshell.net/UB5L9/

Title: How to set Textbox value at page load?