问:
Way of skipping choice tags in xml validation
I have the following XSD:

```<code>  <xs:element name="Parameter" type="complex">
  </xs:element>
  <xs:complexType name="complex">
    <xs:choice>
      <xs:element name="MyData" type="myData"/>
      <xs:element name="String" type="xs:string"/>
    </xs:choice>
    <xs:attribute name="Name" use="required" type="xs:string"/>
  </xs:complexType>
  <xs:complexType name="myData">
     <xs:attribute name="X" use="required" type="xs:integer"/>
     <xs:attribute name="Y" use="required" type="xs:integer"/>
  </xs:complexType>
</code>```

when i validate this

```<code><Parameter Name="P"><MyData X="1" Y="2"></MyData></Parameter>
</code>```

everything is OK, but when i try to validate this:

```<code>        <Parameter Name="P">5r5r5r5r</Parameter>
</code>```

it says "The element 'Parameter' cannot contain text. List of possible elements expected: 'MyData, String'."  Is there a way to skip putting <Sring></String> around "5r5r5r5r"?

答:
So it seems that you want to have a <Parameter> element that can contain other elements or text. This can be achieved by allowing mixed content by setting attribute mixed="true" on <xs:complexType> or <xs:complexContent> element.

Sample code below.

```<code><xs:element name="Parameter">
  <xs:complexType mixed="true">
    <xs:sequence>
      <xs:element name="MyData" type="MyData"/>
    </xs:sequence>
    <xs:attribute name="Name" use="required" type="xs:string"/>
  </xs:complexType>
<xs:element name="Parameter">
</code>```

Note: mixed type allows element to have any of these possible content choices

only text

only elements

both text and elements so that text can appear

before the elements

after the elements

in between the elements

or any combination of the above-mentioned.

You have three questions that all revolve around the same subject. If these answers don't really address your problem then I'm asking you to specify what all requirements you actually want to fulfil.

Is it allowed that element can contain both text and sub-elements at the same time?

Does the text content need to be restricted to some format?

Can the possible sub-elements be any elements or are they restricted to some known elements?

Do you need to be able to validate the sub elements, if they can be any elements?

Body:
I have the following XSD:

  <xs:element name="Parameter" type="complex">
  </xs:element>
  <xs:complexType name="complex">
    <xs:choice>
      <xs:element name="MyData" type="myData"/>
      <xs:element name="String" type="xs:string"/>
    </xs:choice>
    <xs:attribute name="Name" use="required" type="xs:string"/>
  </xs:complexType>
  <xs:complexType name="myData">
     <xs:attribute name="X" use="required" type="xs:integer"/>
     <xs:attribute name="Y" use="required" type="xs:integer"/>
  </xs:complexType>

when i validate this

<Parameter Name="P"><MyData X="1" Y="2"></MyData></Parameter>

everything is OK, but when i try to validate this:

        <Parameter Name="P">5r5r5r5r</Parameter>

it says "The element 'Parameter' cannot contain text. List of possible elements expected: 'MyData, String'."  Is there a way to skip putting <Sring></String> around "5r5r5r5r"?

Body:
So it seems that you want to have a <Parameter> element that can contain other elements or text. This can be achieved by allowing mixed content by setting attribute mixed="true" on <xs:complexType> or <xs:complexContent> element.

Sample code below.

<xs:element name="Parameter">
  <xs:complexType mixed="true">
    <xs:sequence>
      <xs:element name="MyData" type="MyData"/>
    </xs:sequence>
    <xs:attribute name="Name" use="required" type="xs:string"/>
  </xs:complexType>
<xs:element name="Parameter">

Note: mixed type allows element to have any of these possible content choices

only text

only elements

both text and elements so that text can appear

before the elements

after the elements

in between the elements

or any combination of the above-mentioned.

You have three questions that all revolve around the same subject. If these answers don't really address your problem then I'm asking you to specify what all requirements you actually want to fulfil.

Is it allowed that element can contain both text and sub-elements at the same time?

Does the text content need to be restricted to some format?

Can the possible sub-elements be any elements or are they restricted to some known elements?

Do you need to be able to validate the sub elements, if they can be any elements?


来源: stackexchange

问:
API level 29 Intent.ACTION_GET_CONTENT returning wrong id from downloads folder
I am trying to find the full file path for an URI returned from file picker intent. I have downloaded an image from internet which was saved in the browser default download folder. The problem is the id returned by DocumentsContract.getDocumentId(content_describer) is like "msf:254" instead of Long type id generally returned. The code is as following

```<code>public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 101 && resultCode == Activity.RESULT_OK) {
        Uri content_describer = data.getData();
        String src = content_describer.getPath();
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
            imgView.setImageBitmap(bitmap);
        }catch(Exception e){

        }

        Log.e("selected file", content_describer.toString());
        String filename = content_describer.getLastPathSegment();
        Log.e("selected path", filename);
        Log.e("authority",content_describer.getAuthority());

        if (content_describer.getAuthority().equals("com.android.externalstorage.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            final String[] split = docId.split(":");
            final String type = split[0];
            Log.e("npath", "getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    Log.e("nnpath1", Environment.getExternalStorageDirectory() + "/" + split[1]);
                    curFile = Environment.getExternalStorageDirectory() + "/" + split[1];
                } else {
                    Log.e("nnpath2", Environment.getExternalStorageDirectory() + "/");
                }
                // This is for checking SD Card
            } else {
                Log.e("nnpath3", "storage" + "/" + docId.replace(":", "/"));
                curFile = "storage" + "/" + docId.replace(":", "/");
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.downloads.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid",docId);

            Uri ci = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor10 = getActivity().getApplicationContext().getContentResolver().query(ci, projection, null, null,
                    null);
            if (cursor10 != null && cursor10.moveToFirst()) {

                final int column_index = cursor10.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor10.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor10.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.media.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid", docId);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor1 = getActivity().getApplicationContext().getContentResolver().query(contentUri, projection, selection, selectionArgs,
                    null);
            if (cursor1 != null && cursor1.moveToFirst()) {

                final int column_index = cursor1.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor1.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor1.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        Log.e("final path",curFile);

    }
}
</code>```

Please note if I pick the same image going via Image->Downwnload, the above code works normally but when same file is picked from Downloads folder, following error is thrown

```<code>E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flexi.app.android, PID: 15414
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196709, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/msf:253 flg=0x1 }} to activity {com.flexi.app.android/com.flexi.app.android.ProfileActivity}: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4830)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4871)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7319)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
 Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
    at android.content.ContentResolver.query(ContentResolver.java:934)
    at android.content.ContentResolver.query(ContentResolver.java:872)
    at android.content.ContentResolver.query(ContentResolver.java:830)
    at com.flexi.app.android.fragments.ProfileImageFragment.onActivityResult(ProfileImageFragment.java:171)
    at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
    at com.flexi.app.android.ProfileActivity.onActivityResult(ProfileActivity.java:28)
    at android.app.Activity.dispatchActivityResult(Activity.java:8091)
</code>```

The URI is reported as content://com.android.providers.downloads.documents/document/msf%3A253
Any idea what is msf? I have seen image, video, audo but noticed msf for first time.

答:
When you get "msf:xxx" in URI, use below solution:

```<code>if (id != null && id.startsWith("msf:")) {
                    final File file = new File(mContext.getCacheDir(), Constant.TEMP_FILE + Objects.requireNonNull(mContext.getContentResolver().getType(imageUri)).split("/")[1]);
                    try (final InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); OutputStream output = new FileOutputStream(file)) {
                        final byte[] buffer = new byte[4 * 1024]; // or other buffer size
                        int read;

                        while ((read = inputStream.read(buffer)) != -1) {
                            output.write(buffer, 0, read);
                        }

                        output.flush();
                        return file;
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    return null;
                }
</code>```

I have fixed this issue and it's working 100% for msf. :)

Also Delete the temp file after the completion of your work:

```<code>private void deleteTempFile() {
        final File[] files = requireContext().getCacheDir().listFiles();
        if (files != null) {
            for (final File file : files) {
                if (file.getName().contains(Constant.TEMP_FILE)) {
                    file.delete();
                }
            }
        }
    }
</code>```

Here TEMP_FILE value is "temp."

ContentLicense: CC BY-SA 4.0

Body:
I am trying to find the full file path for an URI returned from file picker intent. I have downloaded an image from internet which was saved in the browser default download folder. The problem is the id returned by DocumentsContract.getDocumentId(content_describer) is like "msf:254" instead of Long type id generally returned. The code is as following

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 101 && resultCode == Activity.RESULT_OK) {
        Uri content_describer = data.getData();
        String src = content_describer.getPath();
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
            imgView.setImageBitmap(bitmap);
        }catch(Exception e){

        }

        Log.e("selected file", content_describer.toString());
        String filename = content_describer.getLastPathSegment();
        Log.e("selected path", filename);
        Log.e("authority",content_describer.getAuthority());

        if (content_describer.getAuthority().equals("com.android.externalstorage.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            final String[] split = docId.split(":");
            final String type = split[0];
            Log.e("npath", "getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
            if ("primary".equalsIgnoreCase(type)) {
                if (split.length > 1) {
                    Log.e("nnpath1", Environment.getExternalStorageDirectory() + "/" + split[1]);
                    curFile = Environment.getExternalStorageDirectory() + "/" + split[1];
                } else {
                    Log.e("nnpath2", Environment.getExternalStorageDirectory() + "/");
                }
                // This is for checking SD Card
            } else {
                Log.e("nnpath3", "storage" + "/" + docId.replace(":", "/"));
                curFile = "storage" + "/" + docId.replace(":", "/");
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.downloads.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid",docId);

            Uri ci = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor10 = getActivity().getApplicationContext().getContentResolver().query(ci, projection, null, null,
                    null);
            if (cursor10 != null && cursor10.moveToFirst()) {

                final int column_index = cursor10.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor10.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor10.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        if (content_describer.getAuthority().equals("com.android.providers.media.documents")) {
            final String docId = DocumentsContract.getDocumentId(content_describer);
            Log.e("docid", docId);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            final String column = "_data";
            final String[] projection = {
                    column
            };
            Cursor cursor1 = getActivity().getApplicationContext().getContentResolver().query(contentUri, projection, selection, selectionArgs,
                    null);
            if (cursor1 != null && cursor1.moveToFirst()) {

                final int column_index = cursor1.getColumnIndexOrThrow(column);
                Log.e("imgpp", cursor1.getString(column_index));
                Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
                File fn = new File(cursor1.getString(column_index));
                Log.e("imgpp3", fn.getPath());
                curFile = fn.getPath();
            }
        }

        Log.e("final path",curFile);

    }
}

Please note if I pick the same image going via Image->Downwnload, the above code works normally but when same file is picked from Downloads folder, following error is thrown

E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flexi.app.android, PID: 15414
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196709, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/msf:253 flg=0x1 }} to activity {com.flexi.app.android/com.flexi.app.android.ProfileActivity}: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4830)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4871)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
    at android.os.Handler.dispatchMessage(Handler.java:107)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7319)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
 Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
    at android.content.ContentResolver.query(ContentResolver.java:934)
    at android.content.ContentResolver.query(ContentResolver.java:872)
    at android.content.ContentResolver.query(ContentResolver.java:830)
    at com.flexi.app.android.fragments.ProfileImageFragment.onActivityResult(ProfileImageFragment.java:171)
    at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
    at com.flexi.app.android.ProfileActivity.onActivityResult(ProfileActivity.java:28)
    at android.app.Activity.dispatchActivityResult(Activity.java:8091)

The URI is reported as content://com.android.providers.downloads.documents/document/msf%3A253
Any idea what is msf? I have seen image, video, audo but noticed msf for first time.

Body:
When you get "msf:xxx" in URI, use below solution:

if (id != null && id.startsWith("msf:")) {
                    final File file = new File(mContext.getCacheDir(), Constant.TEMP_FILE + Objects.requireNonNull(mContext.getContentResolver().getType(imageUri)).split("/")[1]);
                    try (final InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); OutputStream output = new FileOutputStream(file)) {
                        final byte[] buffer = new byte[4 * 1024]; // or other buffer size
                        int read;

                        while ((read = inputStream.read(buffer)) != -1) {
                            output.write(buffer, 0, read);
                        }

                        output.flush();
                        return file;
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    return null;
                }

I have fixed this issue and it's working 100% for msf. :)

Also Delete the temp file after the completion of your work:

private void deleteTempFile() {
        final File[] files = requireContext().getCacheDir().listFiles();
        if (files != null) {
            for (final File file : files) {
                if (file.getName().contains(Constant.TEMP_FILE)) {
                    file.delete();
                }
            }
        }
    }

Here TEMP_FILE value is "temp."


问:
How to move dataframe variable names to first row and add new variable names to multiple dataframes in a list?

library(purrr)
library(tibble)
library(dplyr)
```

<p>Starting list of dataframes</p>

```lst <- list(df1 = data.frame(X.1 = as.character(1:2),
                             heading = letters[1:2]),
            df2 =  data.frame(X.32 = as.character(3:4),
                              another.topic = paste("Line ", 1:2)))

lst
#> $df1
#>   X.1 heading
#> 1   1       a
#> 2   2       b
#>
#> $df2
#>   X.32 another.topic
#> 1    3       Line  1
#> 2    4       Line  2
```

<p>Expected "combined" dataframe, with  new consistent variable names, and old variable names in the first row of each constituent dataframe.</p>

```#>    id   h1            h2
#> 1 df1  X.1       heading
#> 2 df1    1             a
#> 3 df1    2             b
#> 4 df2 X.32 another.topic
#> 5 df2    3       Line  1
#> 6 df2    4       Line  2

```

<p><code>add_row</code> requires "Name-value pairs, passed on to tibble(). Values can be defined only for columns that already exist in .data and unset columns will get an NA value."</p>

<p>Which is what I think I have achieved with this:</p>

```df_nms <-
  map(lst, names) %>%
  map(set_names)

#> $df1
#>       X.1   heading
#>     "X.1" "heading"
#>
#> $df2
#>            X.32   another.topic
#>          "X.32" "another.topic"

```

<p>But I cannot tie up the last bit, using a purrr function to add the names to the head of each dataframe. I've tried numerous variations with <code>map2</code> and <code>pmap</code>  the closest I can get at present (if I treat <code>add_row</code> as a formula , prefixing it with <code>~</code> and remove the <code>.y</code> I get a new first row populated with NAs). I think I'm missing how to pass the name-value pairs to the add_row function.</p>

```map2(lst, df_nms, add_row(.x, .y, .before = 1)) %>%
  map(set_names, c("h1", "h2")) %>%
  map_dfr(bind_rows, .id = "id")
#> Error in add_row(.x, .y, .before = 1): object '.x' not found

```

A pointer to resolve this last step would be most appreciated.

答:
I altered your sample data a bit, setting stringsAsFactors to FALSE when creating the data.frames in lst.

here is a solution using data.table::rbindlist().

```<code>#sample data
lst <- list(df1 = data.frame(X.1 = as.character(1:2),
                             heading = letters[1:2],
                             stringsAsFactors = FALSE),   # !! <--
            df2 =  data.frame(X.32 = as.character(3:4),
                              another.topic = paste("Line ", 1:2),
                              stringsAsFactors = FALSE)   # !! <--
            )

DT <- data.table::rbindlist( lapply( lst, function(x) rbind( names(x), x ) ),
                             use.names = FALSE, idcol = "id" )
setnames(DT, names( lst[[1]] ), c("h1", "h2") )

#     id   h1            h2
# 1: df1  X.1       heading
# 2: df1    1             a
# 3: df1    2             b
# 4: df2 X.32 another.topic
# 5: df2    3       Line  1
# 6: df2    4       Line  2
</code>```

Body:
library(purrr)
library(tibble)
library(dplyr)

Starting list of dataframes

lst <- list(df1 = data.frame(X.1 = as.character(1:2),
                             heading = letters[1:2]),
            df2 =  data.frame(X.32 = as.character(3:4),
                              another.topic = paste("Line ", 1:2)))

lst
#> $df1
#>   X.1 heading
#> 1   1       a
#> 2   2       b
#>
#> $df2
#>   X.32 another.topic
#> 1    3       Line  1
#> 2    4       Line  2

Expected "combined" dataframe, with  new consistent variable names, and old variable names in the first row of each constituent dataframe.

#>    id   h1            h2
#> 1 df1  X.1       heading
#> 2 df1    1             a
#> 3 df1    2             b
#> 4 df2 X.32 another.topic
#> 5 df2    3       Line  1
#> 6 df2    4       Line  2

add_row requires "Name-value pairs, passed on to tibble(). Values can be defined only for columns that already exist in .data and unset columns will get an NA value."

Which is what I think I have achieved with this:

df_nms <-
  map(lst, names) %>%
  map(set_names)

#> $df1
#>       X.1   heading
#>     "X.1" "heading"
#>
#> $df2
#>            X.32   another.topic
#>          "X.32" "another.topic"

But I cannot tie up the last bit, using a purrr function to add the names to the head of each dataframe. I've tried numerous variations with map2 and pmap  the closest I can get at present (if I treat add_row as a formula , prefixing it with ~ and remove the .y I get a new first row populated with NAs). I think I'm missing how to pass the name-value pairs to the add_row function.

map2(lst, df_nms, add_row(.x, .y, .before = 1)) %>%
  map(set_names, c("h1", "h2")) %>%
  map_dfr(bind_rows, .id = "id")
#> Error in add_row(.x, .y, .before = 1): object '.x' not found

A pointer to resolve this last step would be most appreciated.

Body:
I altered your sample data a bit, setting stringsAsFactors to FALSE when creating the data.frames in lst.

here is a solution using data.table::rbindlist().

#sample data
lst <- list(df1 = data.frame(X.1 = as.character(1:2),
                             heading = letters[1:2],
                             stringsAsFactors = FALSE),   # !! <--
            df2 =  data.frame(X.32 = as.character(3:4),
                              another.topic = paste("Line ", 1:2),
                              stringsAsFactors = FALSE)   # !! <--
            )

DT <- data.table::rbindlist( lapply( lst, function(x) rbind( names(x), x ) ),
                             use.names = FALSE, idcol = "id" )
setnames(DT, names( lst[[1]] ), c("h1", "h2") )

#     id   h1            h2
# 1: df1  X.1       heading
# 2: df1    1             a
# 3: df1    2             b
# 4: df2 X.32 another.topic
# 5: df2    3       Line  1
# 6: df2    4       Line  2


问:
How can I set the height of an element equal to another element? (Codepen included)
I have two Bootstrap columns with 4 divs (2 in each):

```<code><div class="row">
  <div class="col-8">
    <div class="cell-1">
      Cell 1
    </div>
    <div class="cell-2">
      Cell 2
      <ul>
        <li>Some repeatable text</li>
        <li>Some repeatable text</li>
      </ul>
    </div>
  </div>
  <div class="col-4">
    <div class="cell-3">
      Cell 3
    </div>
    <div class="cell-4" style="overflow-y:auto; max-height:[height of cell-2]">
      Cell 4
      <ul>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
      </ul>
    </div>
  </div>
</div>
</code>```

.cell-4 has overflow-y: auto. How can I set the max-height of .cell-4 equal to the dynamic height of .cell-2?

Ideally without Javacript.

Codepen here: link

答:
I have modified the CSS flexbox configuration to make it work. col-4 and col-8 are configured to flex column. Then, cell-4 add the flex-basis and flex-grow configuration.

.cell-1{
  background: red;
}
.cell-2{
  background: blue;
}
.cell-3{
  background: green;
}
.cell-4{
  background: pink;
  overflow-x: hidden;
  /* overflow-y: scroll; */
  /* max-height: 50px; // Set this to equal height of Cell 2 */
  /* Addition flex configuration to make it work */
  flex-basis: 0px;
  flex-grow: 1;
  overflow-y: auto;
}

/* Addition flex configuration to make it work */
.col-4, .col-8 {
  display: flex;
  flex-direction: column;
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

<div class="row">
  <div class="col-8">
    <div class="cell-1">
      Cell 1
    </div>
    <div class="cell-2">
      Cell 2
      <ul>
        <li>Some repeatable text</li>
        <li>Some repeatable text</li>
      </ul>
    </div>
  </div>
  <div class="col-4">
    <div class="cell-3">
      Cell 3
    </div>
    <div class="cell-4" style="overflow-y:auto; max-height:[height of cell-2]">
      Cell 4
      <ul>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
      </ul>
    </div>
  </div>
</div></code>```

Body:
I have two Bootstrap columns with 4 divs (2 in each):

      Cell 1

      Cell 2

Some repeatable text

Some repeatable text

      Cell 3

      Cell 4

Lots of repeatable text

Lots of repeatable text

Lots of repeatable text

Lots of repeatable text

Lots of repeatable text

Lots of repeatable text

.cell-4 has overflow-y: auto. How can I set the max-height of .cell-4 equal to the dynamic height of .cell-2?

Ideally without Javacript.

Codepen here: link

Body:
I have modified the CSS flexbox configuration to make it work. col-4 and col-8 are configured to flex column. Then, cell-4 add the flex-basis and flex-grow configuration.

.cell-1{
  background: red;
}
.cell-2{
  background: blue;
}
.cell-3{
  background: green;
}
.cell-4{
  background: pink;
  overflow-x: hidden;
  /* overflow-y: scroll; */
  /* max-height: 50px; // Set this to equal height of Cell 2 */
  /* Addition flex configuration to make it work */
  flex-basis: 0px;
  flex-grow: 1;
  overflow-y: auto;
}

/* Addition flex configuration to make it work */
.col-4, .col-8 {
  display: flex;
  flex-direction: column;
}

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

<div class="row">
  <div class="col-8">
    <div class="cell-1">
      Cell 1
    </div>
    <div class="cell-2">
      Cell 2
      <ul>
        <li>Some repeatable text</li>
        <li>Some repeatable text</li>
      </ul>
    </div>
  </div>
  <div class="col-4">
    <div class="cell-3">
      Cell 3
    </div>
    <div class="cell-4" style="overflow-y:auto; max-height:[height of cell-2]">
      Cell 4
      <ul>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
        <li>Lots of repeatable text</li>
      </ul>
    </div>
  </div>
</div>


问:
Detect Ctrl+C in Java Console
I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call).
With KeyListener it doesn't work on the console (only with JFrame as far as I know).

I couldn't find a solution to my problem on the internet.

Do I have to do it with Runtime? I have tried it, but it didn't work...

```<code>Runtime.getRuntime().addShutdownHook(new Thread()
{
    public void run()
    {
        Test.mainThread.interrupt();
    }
});
</code>```

There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java

答:
We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:

```<code>Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    // Do something to save the score
}));
</code>```

Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:

```<code>Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    gameScores.save(); // assuming we have a gameScores object in this scope
}));
</code>```

Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.

Title: Detect Ctrl+C in Java Console

Body:
I have a Console-Java game. The score from the game will be saved in a JSON file if Ctrl+C is pressed. The process to save the score in a JSON file works. But I don't know, how to detect Ctrl+C from the console and if this happens, I will save the score (just a method call).
With KeyListener it doesn't work on the console (only with JFrame as far as I know).

I couldn't find a solution to my problem on the internet.

Do I have to do it with Runtime? I have tried it, but it didn't work...

Runtime.getRuntime().addShutdownHook(new Thread()
{
    public void run()
    {
        Test.mainThread.interrupt();
    }
});

There are similar questions on Stackoverflow, but not for use on the console Catching Ctrl+C in Java

Body:
We know that CTRL-C closes the application and shuts down the JVM. And since it is a normal shutdown, it runs the shutdown hooks. So creating a shutdown hook is a correct approach:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    // Do something to save the score
}));

Note that we're passing a Runnable here as the shutdown task. So we can pass an object that has the required functionality:

Runtime.getRuntime().addShutdownHook(new Thread(() -> {
    gameScores.save(); // assuming we have a gameScores object in this scope
}));

Your initial attempt by interrupting the thread can be viewed as a variant of this approach. Instead of passing the business object - gameScores - we can pass the thread to interrupt it later. But it's better to operate on the business level.


问:
How to generate 34 alphanumerics with a pattern in PHP?
I want to generate 34 random letters (capitalized and not) and numbers. Before the generated 34 random alphanumerics there is a word pro_sec_ which is there everytime it generate. And the 25th & 26th is 00

So the generated result will be: (just an example)

pro_sec_Vy6Q67sh6HvP90j7gWnq6SxN00p8Gapu66

Another ex.
pro_sec_6B57nTshusbnay6esjabxns800nGvaz2Lov

The pro_sec_ and the 00 there in 25th and 26th are always the same and the rest are just generated.

答:
This should work for you:</p>

```<code><?php
function getToken($n) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';

    for ($i = 0; $i < $n; $i++) {
        $index = rand(0, strlen($characters) - 1);
        $randomString .= $characters[$index];
    }

    return $randomString;
}

echo 'pro_sec_' . getToken(24) . '00' . getToken(9);
</code>```

Body:
This should work for you:

<?php
function getToken($n) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';

    for ($i = 0; $i < $n; $i++) {
        $index = rand(0, strlen($characters) - 1);
        $randomString .= $characters[$index];
    }

    return $randomString;
}

echo 'pro_sec_' . getToken(24) . '00' . getToken(9);


问:
What are the benefits of a Hypervisor VM?
I'm looking into using virtual machines to host multiple OSes and I'm looking at the free solutions which there are a lot of them. I'm confused by what a hypervisor is and why are they different or better than a "standard" virtual machine. When I mean standard I going to use the benchmark virtual machine VMWare Server 2.0.

For a dual core system with 4 GB of ram that would be capable of running a max of 3 VMs. Which is the best choice? Hypervisor or non-hypervisor and why? I've already read the Wikipedia article but the technical details are over my head. I need a basic answer of what can these different VM flavors do for me.

My main question relates to how I would do testing on multiple environments. I am concerned about the isolation of OSes so I can test applications on multiple OSes at the same time. Also which flavor gives a closer experience of how a real machine operates?

I'm considering the following:

(hypervisor)

Xen

Hyper-V

(non-hypervisor)

VirtualBox

VMWare Server 2.0

Virtual PC 2007

*The classifications of the VMs I've listed may be incorrect.

答:
Disclaimer, everything below is (broadly) my opinion.

Its helpful to consider a virtual machine monitor (a hypervisor) as a very small microkernel. It has very few jobs beyond accessing the underlying hardware, such as monitoring of event channels and granting guest domains access to specific resources .. while enforcing some kind of scheduler.

All guest machines are completely oblivious of the others, the isolation is true. Guests do not share memory with the privileged guest (or each other). So, in this instance, you could (roughly) think of each guest (even the privileged one) as a process, as far as the VMM is concerned. Typically, the first guest gets extra privileges so that it can manage the rest. This is the ideal technology to use when virtual machines are put into production and exposed to the world.

Additionally, some guests can be patched to become aware of the hypervisor, significantly increasing their performance.

On the other hand we have things like VMWare and QEMU, which rely on the host kernel to give it access to bare metal and enough memory to exist. They assume that all guests need to be presented with a complete machine, the limits put on the process presenting these (more or less) become the limits of the virtual machine. I say more or less because device mapper QoS is not commonly implemented. This is the ideal solution for trying code in some other OS, or some other architecture. A lot of people will call QEMU, Simics or even sometimes VMWare (depending on the product) a 'simulator'.

For production roll outs I use Xen, for testing something I just cross compiled I use QEMU, Simics or VirtualBox.

If you are just testing / rolling new code on various operating systems and architectures, I highly recommend #2. If your need is introspection (i.e. watching guest memory change as bad programs run in a guest) ... I'd need more explanation before answering.

OwnerDisplayName: Jeremy Edwards

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: Jeremy Edwards

OwnerDisplayName: tinkertim

LastEditorDisplayName: tinkertim


问:
Thread synchronization problem
I use Qt and C++. I have a list of threads (Qlist<QtThread>).

I try to synchronize them. All threads calculate some values. And I want to take them.

Have you any ideas? thank a lot

答:
Your question is a bit broad, but Qt has a lot of documentation on different thread synchronization methods.

The base of the docs is at Threading Support in Qt. The specific part you should find the info in is the Synchronizing Threads section. It lists the various mutex, locks, semaphores, wait conditions that are available in the Qt framework.

The documentation for all these classes has example usage code. Also have a look at the Threading and Concurrent Programming Examples, you'll probably find what you're after in there.

ContentLicense: CC BY-SA 3.0

Title: Thread synchronization problem


问:
Multiple (redundant?) reads of the same file when reading in files into a spark dataframe then using randomSplit()
I'm reading in a set of files into a pyspark dataframe then using randomSplit() to split it into 3 subsets. I noticed from the logging that it seems to read each file of the dataset 4 times. My question is, are the multiple reads necessary (or redundant), and if not, is there a way to cache it to minimize the number of times each file needs to be read?

Example:

My data files are set up this way:

```<code>/somedir/data/ID=123/123_0.jsonl
/somedir/data/ID=123/123_1.jsonl
/somedir/data/ID=123/123_2.jsonl

/somedir/data/ID=456/456_0.jsonl
/somedir/data/ID=456/456_1.jsonl
/somedir/data/ID=456/456_2.jsonl
</code>```

My script:

```<code>df = spark.read.json('/somedir/data')
df = df.repartition('ID')
splits = df.randomSplit(weights=[0.6, 0.2, 0.2])

for df_split, label in zip(splits, ['train', 'test', 'validation']):
    df_split.write.partitionBy('ID').json(os.path.join('/somedir/split', label))
</code>```

What I'm noticing in the logs:

```<code>2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [empty row]
2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [empty row]
2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [empty row]
...some other lines...
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]
...some other lines...
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]
...some other lines...
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]

...repeat for ID=456...
</code>```

I tried adding this line: splits = [df_split.persist() for df_split in splits] after the randomSplit() line but before the write loop but it didn't seem to help.

Any thoughts appreciated!

答:
It seems I put the persist() in the wrong part. If I persist right after the spark.read line, the number of reads of the same file is reduced to 2 (no matter how many randomSplit subsets).</p>

```<code>df = spark.read.json('/somedir/data')
df = df.persist()
</code>```

Body:
I'm reading in a set of files into a pyspark dataframe then using randomSplit() to split it into 3 subsets. I noticed from the logging that it seems to read each file of the dataset 4 times. My question is, are the multiple reads necessary (or redundant), and if not, is there a way to cache it to minimize the number of times each file needs to be read?

Example:

My data files are set up this way:

/somedir/data/ID=123/123_0.jsonl
/somedir/data/ID=123/123_1.jsonl
/somedir/data/ID=123/123_2.jsonl

/somedir/data/ID=456/456_0.jsonl
/somedir/data/ID=456/456_1.jsonl
/somedir/data/ID=456/456_2.jsonl

My script:

df = spark.read.json('/somedir/data')
df = df.repartition('ID')
splits = df.randomSplit(weights=[0.6, 0.2, 0.2])

for df_split, label in zip(splits, ['train', 'test', 'validation']):
    df_split.write.partitionBy('ID').json(os.path.join('/somedir/split', label))

What I'm noticing in the logs:

2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [empty row]
2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [empty row]
2020-06-01 00:48:33 INFO  FileScanRDD:54 - Reading File path: file:/somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [empty row]
...some other lines...
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:34 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]
...some other lines...
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:35 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]
...some other lines...
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_0.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_1.jsonl, range: 0-1000000, partition values: [123]
2020-06-01 00:48:36 INFO  FileScanRDD:54 - Reading File path: file:///somedir/data/ID=123/123_2.jsonl, range: 0-1000000, partition values: [123]

...repeat for ID=456...

I tried adding this line: splits = [df_split.persist() for df_split in splits] after the randomSplit() line but before the write loop but it didn't seem to help.

Any thoughts appreciated!

Body:
It seems I put the persist() in the wrong part. If I persist right after the spark.read line, the number of reads of the same file is reduced to 2 (no matter how many randomSplit subsets).

df = spark.read.json('/somedir/data')
df = df.persist()


问:
How to get numbers of variants numerical combinations in javascript?
I need to implement a function that accepts two parameters - the number of 0 and the number of 1 and determine how many ways to place these 0 and 1 so that there are no two zeros in a row.

For example, I need to find all methods of placing two 0 and two 1.

There are six possible ways to place them: 0011, 0101, 0110, 1001, 1010, 1100.

In three cases there are two zeros in a row: 0011, 1001 and 1100.

I subtract them from the total number and get three possible ways: 0101, 0110 and 1010. So the answer is 3.

First, I'm trying to write script to recognize which cases I need

let arr = ["1100","1010","1001","0011","0101","0110"]
let result = [];
for (let i = 0; i < arr.length; i++){
  let expVal = arr[i];
  for (let p = 0; p < expVal.length; p++){
    if (expVal[p] === expVal[p++] || expVal[p] === "0"){
      result.push(expVal)
    }
  }
}
console.log(result);```

It's does not work. I don't know how to fix it.
And I don't understand what I need to do later

答:
There are 2 issues with the code, as far as I can see:

You're incrementing p two times: once in the for definition, and once in the execution itself (p++). The second one should be replaced by p+1

Also, you're checking if the next character is equal to the current, OR the current character is 0. This should be AND.

let arr = ["1100","1010","1001","0011","0101","0110"]
let result = [];
for (let i = 0; i < arr.length; i++){
  let expVal = arr[i];
  for (let p = 0; p < expVal.length; p++){
    if (expVal[p] === expVal[p+1] && expVal[p] === "0"){
      result.push(expVal)
    }
  }
}
console.log(result);```

Changing those two things fixes it.

Body:
I need to implement a function that accepts two parameters - the number of 0 and the number of 1 and determine how many ways to place these 0 and 1 so that there are no two zeros in a row.

For example, I need to find all methods of placing two 0 and two 1.

There are six possible ways to place them: 0011, 0101, 0110, 1001, 1010, 1100.

In three cases there are two zeros in a row: 0011, 1001 and 1100.

I subtract them from the total number and get three possible ways: 0101, 0110 and 1010. So the answer is 3.

First, I'm trying to write script to recognize which cases I need

let arr = ["1100","1010","1001","0011","0101","0110"]
let result = [];
for (let i = 0; i < arr.length; i++){
  let expVal = arr[i];
  for (let p = 0; p < expVal.length; p++){
    if (expVal[p] === expVal[p++] || expVal[p] === "0"){
      result.push(expVal)
    }
  }
}
console.log(result);

It's does not work. I don't know how to fix it.
And I don't understand what I need to do later

Body:
There are 2 issues with the code, as far as I can see:

You're incrementing p two times: once in the for definition, and once in the execution itself (p++). The second one should be replaced by p+1

Also, you're checking if the next character is equal to the current, OR the current character is 0. This should be AND.

let arr = ["1100","1010","1001","0011","0101","0110"]
let result = [];
for (let i = 0; i < arr.length; i++){
  let expVal = arr[i];
  for (let p = 0; p < expVal.length; p++){
    if (expVal[p] === expVal[p+1] && expVal[p] === "0"){
      result.push(expVal)
    }
  }
}
console.log(result);

Changing those two things fixes it.


问:
How can I sort data entries so that a range of data is grouped together in Python, or Google Sheets?
For instance, given a dataset of various weights and names, how can I group individuals with similar weights (+/- 5% the weight I want) together?

Thank you!

答:
I understand that you want to divide your data in groups where the maximum difference from the biggest to the smaller is ±5%. I wrote an Apps Script code that can do that in your Sheet.  First, I wrote an example Sheet with student names and test scores (from 0 to 10) instead of names and heights; I'll explain why later. This is the initial state of the example sheet:

In the Group column the code will drop the group ID as an integer starting at 0. This is the code:

function so62060595() {
  var dataColumn = 2; // Column B
  var groupColumn = 3; // Column C
  var dataSheet = SpreadsheetApp.getActive().getActiveSheet();
  var dataRange = dataSheet.getRange(2, 1, dataSheet.getLastRow() - 1, dataSheet
    .getLastColumn()).sort({
    column: dataColumn,
    ascending: false
  });
  var data = dataRange.getValues();
  var groupingPercentage = 5 / 100 // 5%
  var upperBound = data[0][dataColumn - 1];
  var groupID = 0;

  for (var r = 0; r < data.length; r++) {
    if (upperBound - upperBound * groupingPercentage <= data[r][dataColumn -
      1] + data[r][dataColumn - 1] * groupingPercentage) {
      // Include in the same group
      data[r][groupColumn - 1] = groupID;
    } else {
      // Create a new group
      var groupID = groupID + 1;
      var upperBound = data[r][dataColumn - 1];

      data[r][groupColumn - 1] = groupID;
    }
  }

  dataRange.setValues(data);
}
```

<p>The first thing that the code does is to open the sheet with <code>SpreadsheetApp.getActive()</code>, <code>Spreadsheet.getActiveSheet()</code>. After that, the code looks for the data range with <code>Sheet.getRange()</code> (notice how it uses <code>Sheet.getLastRow()</code> and <code>Sheet.getLastColumn()</code> to find the range size) and sorts it with <code>Range.sort()</code> using the score column as a reference. Later, it reads the range with <code>Range.getValues()</code>. Also, I initialized some variables like the ID and group columns, the desired grouping percentage (5%) in this case and the initial group ID (<code>0</code>).</p>

<p>After all that initialization the code will iterate over every row and check if the data value (<code>Score</code> in the example) is at a ±5% of distance to the upper bound of the group (the highest value in the group). If the value is in the ±5% range, the group ID will be dropped. If it's not in the range, a new group ID will be generated and the upper bound taken from that entry. The process will continue until all entries have a group ID, and after that the data will be entered in the table with <code>Range.setValues()</code>. The final result looks like this:</p>

<p><img src="https://i.stack.imgur.com/Kcz1v.png" alt="Final example"></p>

<p>And now, why did I use test scores instead of heights? Well, look what happens with an example of heights using the previous code:</p>

<p><img src="https://i.stack.imgur.com/l9LLJ.png" alt="Heights example"></p>

<p>Only two groups are generated (<code>0</code> and <code>1</code>) because the distance between realistic heights is smaller than ±5%. I hope that my answer helps you, but don't hesitate to ask me any additional doubt.</p>

<hr>

<h1>UPDATE</h1>

<p>Based on the question update in your comment I modified the script. If I understand correctly, you want a midpoint in each group and calculate the group bounds based on that midpoint plus/minus 5%. If my assumption is correct, you can use the following code:</p>

<pre class="lang-js prettyprint-override"><code>function calculateGroupBounds(groupingPercentage, groupUpperBound) {
  var groupBounds = {};
  groupBounds['groupUpperBound'] = groupUpperBound;
  groupBounds['groupMidpoint'] = 100 * groupUpperBound / (100 +
    groupingPercentage);
  groupBounds['groupLowerBound'] = (100 - groupingPercentage) * groupBounds[
    'groupMidpoint'] / 100;

  return groupBounds;
}

function so62060595B() {
  // Sheet reading
  var dataColumn = 2; // Column B
  var groupColumn = 3; // Column C
  var dataSheet = SpreadsheetApp.getActive().getActiveSheet();
  var dataRange = dataSheet.getRange(2, 1, dataSheet.getLastRow() - 1, dataSheet
    .getLastColumn()).sort({
    column: dataColumn,
    ascending: false
  });
  var data = dataRange.getValues();

  // Group initialization
  var groupingPercentage = 5; // 5%
  var groupID = 0;
  var groupUpperBound = data[0][dataColumn - 1];
  var groupBounds = calculateGroupBounds(groupingPercentage, groupUpperBound)
  var groupMidpoint = groupBounds['groupMidpoint'];
  var groupLowerBound = groupBounds['groupLowerBound'];

  for (var r = 0; r < data.length; r++) {
    if (data[r][dataColumn - 1] <= groupUpperBound && data[r][dataColumn - 1] >=
      groupLowerBound) {
      // Include in the same group
      data[r][groupColumn - 1] = groupID;
    } else {
      // Create a new group
      var groupID = groupID + 1;
      var upperBound = data[r][dataColumn - 1];
      var groupBounds = calculateGroupBounds(groupingPercentage,
        upperBound)
      var groupMidpoint = groupBounds['groupMidpoint'];
      var groupLowerBound = groupBounds['groupLowerBound'];

      data[r][groupColumn - 1] = groupID;
    }
  }

  dataRange.setValues(data);
}
</code>```

This new code uses the same Apps Script methods as the previous one and includes a new function (calculateGroupBounds()) to compute the upper and lower bounds and the midpoint. In the data iteration the code will check if the value falls between the upper and lower bound, and if it does the group iD will be dropped. If it doesn't a new group will be created. This is the result with the same example data as the previous code:

And this is the result with the heights table:

These results are the same as the previous code even though we use a different approach in this second code. This is because on the first code I used mathematical properties to divide the data in ±5% groups without calculating the midpoint. Please, ask me any doubts if you still need help.

Body:
I understand that you want to divide your data in groups where the maximum difference from the biggest to the smaller is ±5%. I wrote an Apps Script code that can do that in your Sheet.  First, I wrote an example Sheet with student names and test scores (from 0 to 10) instead of names and heights; I'll explain why later. This is the initial state of the example sheet:

In the Group column the code will drop the group ID as an integer starting at 0. This is the code:

function so62060595() {
  var dataColumn = 2; // Column B
  var groupColumn = 3; // Column C
  var dataSheet = SpreadsheetApp.getActive().getActiveSheet();
  var dataRange = dataSheet.getRange(2, 1, dataSheet.getLastRow() - 1, dataSheet
    .getLastColumn()).sort({
    column: dataColumn,
    ascending: false
  });
  var data = dataRange.getValues();
  var groupingPercentage = 5 / 100 // 5%
  var upperBound = data[0][dataColumn - 1];
  var groupID = 0;

  for (var r = 0; r < data.length; r++) {
    if (upperBound - upperBound * groupingPercentage <= data[r][dataColumn -
      1] + data[r][dataColumn - 1] * groupingPercentage) {
      // Include in the same group
      data[r][groupColumn - 1] = groupID;
    } else {
      // Create a new group
      var groupID = groupID + 1;
      var upperBound = data[r][dataColumn - 1];

      data[r][groupColumn - 1] = groupID;
    }
  }

  dataRange.setValues(data);
}

The first thing that the code does is to open the sheet with SpreadsheetApp.getActive(), Spreadsheet.getActiveSheet(). After that, the code looks for the data range with Sheet.getRange() (notice how it uses Sheet.getLastRow() and Sheet.getLastColumn() to find the range size) and sorts it with Range.sort() using the score column as a reference. Later, it reads the range with Range.getValues(). Also, I initialized some variables like the ID and group columns, the desired grouping percentage (5%) in this case and the initial group ID (0).

After all that initialization the code will iterate over every row and check if the data value (Score in the example) is at a ±5% of distance to the upper bound of the group (the highest value in the group). If the value is in the ±5% range, the group ID will be dropped. If it's not in the range, a new group ID will be generated and the upper bound taken from that entry. The process will continue until all entries have a group ID, and after that the data will be entered in the table with Range.setValues(). The final result looks like this:

And now, why did I use test scores instead of heights? Well, look what happens with an example of heights using the previous code:

Only two groups are generated (0 and 1) because the distance between realistic heights is smaller than ±5%. I hope that my answer helps you, but don't hesitate to ask me any additional doubt.

UPDATE

Based on the question update in your comment I modified the script. If I understand correctly, you want a midpoint in each group and calculate the group bounds based on that midpoint plus/minus 5%. If my assumption is correct, you can use the following code:

function calculateGroupBounds(groupingPercentage, groupUpperBound) {
  var groupBounds = {};
  groupBounds['groupUpperBound'] = groupUpperBound;
  groupBounds['groupMidpoint'] = 100 * groupUpperBound / (100 +
    groupingPercentage);
  groupBounds['groupLowerBound'] = (100 - groupingPercentage) * groupBounds[
    'groupMidpoint'] / 100;

  return groupBounds;
}

function so62060595B() {
  // Sheet reading
  var dataColumn = 2; // Column B
  var groupColumn = 3; // Column C
  var dataSheet = SpreadsheetApp.getActive().getActiveSheet();
  var dataRange = dataSheet.getRange(2, 1, dataSheet.getLastRow() - 1, dataSheet
    .getLastColumn()).sort({
    column: dataColumn,
    ascending: false
  });
  var data = dataRange.getValues();

  // Group initialization
  var groupingPercentage = 5; // 5%
  var groupID = 0;
  var groupUpperBound = data[0][dataColumn - 1];
  var groupBounds = calculateGroupBounds(groupingPercentage, groupUpperBound)
  var groupMidpoint = groupBounds['groupMidpoint'];
  var groupLowerBound = groupBounds['groupLowerBound'];

  for (var r = 0; r < data.length; r++) {
    if (data[r][dataColumn - 1] <= groupUpperBound && data[r][dataColumn - 1] >=
      groupLowerBound) {
      // Include in the same group
      data[r][groupColumn - 1] = groupID;
    } else {
      // Create a new group
      var groupID = groupID + 1;
      var upperBound = data[r][dataColumn - 1];
      var groupBounds = calculateGroupBounds(groupingPercentage,
        upperBound)
      var groupMidpoint = groupBounds['groupMidpoint'];
      var groupLowerBound = groupBounds['groupLowerBound'];

      data[r][groupColumn - 1] = groupID;
    }
  }

  dataRange.setValues(data);
}

This new code uses the same Apps Script methods as the previous one and includes a new function (calculateGroupBounds()) to compute the upper and lower bounds and the midpoint. In the data iteration the code will check if the value falls between the upper and lower bound, and if it does the group iD will be dropped. If it doesn't a new group will be created. This is the result with the same example data as the previous code:

And this is the result with the heights table:

These results are the same as the previous code even though we use a different approach in this second code. This is because on the first code I used mathematical properties to divide the data in ±5% groups without calculating the midpoint. Please, ask me any doubts if you still need help.


问:
Update SQL from PHP with textbox and button
I am simply trying to create a home webpage to where we can enter the mileage hit update which grabs the vehicle, and current date then pushes it to the DB.

The code I have below displays correctly other than maybe formatting the number to have a , but that wouldn't be a necessity.

When I hit update I get Notice: Undefined variable: mileage in /var/www/html/Oil/cars.php on line 60

```<code><link href="status.css" rel="stylesheet">
<body bgcolor = #000000>
<font color = "white">

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
 <META HTTP-EQUIV="refresh" CONTENT="86400"><style>
        body {
            animation: fadeInAnimation ease 3s;
            animation-iteration-count: 1;
            animation-fill-mode: forwards;
        }
        @keyframes fadeInAnimation {
            0% {
                opacity: 0;
            }
            100% {
                opacity: 1;
            }
        }
    </style>
</head>

<center>
<font color = "red">

<?php
try {

    $db = new PDO("sqlite:/var/www/html/Oil/Vehicles.db");
    print "<center><table border=10 bordercolorlight=#383838 bordercolordark=Gray>";
    print "<tr><td class='toprow'><u>Vehicle</u></td><td class='toprow'><u>Mileage</u></td><td class='toprow'><u>Filter Size</u></td><td class='toprow'><u>Oil Capacity</u></td><td class='toprow'><u>Oil Type</u></td><td class='toprow'><u>Change Date</u></td><td class='toprow'><u>New Miles</u></td><td class='toprow'><u>Update</u></td></tr>";
    $result2 = $db->query('SELECT * FROM Cars');

    foreach ($result2 as $row) {

        print '<tr><td>' . $row['vehicle'] .'</td>';
        print "<td>" . $row['mileage'] . "</td>";
        print '<td>' . $row['filter'] .'</td>';
        print '<td>' . $row['oilCap'] .'</td>';
        print '<td>' . $row['oilType'] .'</td>';
        print '<td>' . $row['changeDate'] .'</td>';
    print '<td><form action="" method="POST"><input type="Text" name= "mileage"/><input type="hidden" name="vehicle" value="' .$row['vehicle']. '"/></td>';
    print '<td><button class="btn btn-default" type="submit" name="update">Update</button></form></td></tr>';
    }
    print "</table></center>";

} catch (PDOException $e) {
    echo $e->getMessage();
}
if (isset($_POST['update'])) {
    ini_set('display_errors', 1);
    error_reporting(E_ALL);

    $mileage = $_POST['mileage'];
    print $mileage;
    $vehicle = $_POST['vehicle'];
    print $vehicle;
    $change = date("m/d/Y");
    print $change;

    $sql = "UPDATE cars SET mileage = :mileage, chageDate = :change WHERE vehicle = :vehicle";

    try{
            $db2 = new PDO("sqlite:/var/www/html/Oil/Vehicles.db");
        if (!($results = $db2->prepare($sql))){
            echo "Prepare failed: (" . $db->errorInfo() . ") " . $db->errorCode();
        }elseif (!$results->bindValue(':mileage', $mileage)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->bindValue(':change', $change)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->bindValue(':vehicle', $vehicle)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->execute()) {
            echo "Execute failed:\n";
            print_r($results->errorInfo());
        }else{
            $count = $results ->rowCount();
            if($results ->rowCount() == 0)
                echo 'Error';
            else
                echo 'Changed!';
        }

        } catch (PDOException $e) {
            echo $e->getMessage();
        }

}

?>

</code>```

Maybe I'm not passing mileage correctly?

答:
In your code,

The line 59 and 60 as you said are:

$milage = $_POST['mileage'];
print $mileage;
```

<p>You are assigning the value from form field to <code>$milage</code>, but you are trying to print a variable named <code>$mileage</code>. Check the spelling. They are different. So the variable you are trying to print is obviously <code>undefined</code>.</p>

<p>Change the code to,</p>

<pre class="lang-php prettyprint-override"><code>$mileage= $_POST['mileage'];
print $mileage;
</code>```

Eventhough, it's just a typo. It can cause lot of debug time. So, try to understand the error and the problem will be somewhere beside it or it will have some relation atleast.

Body:
I am simply trying to create a home webpage to where we can enter the mileage hit update which grabs the vehicle, and current date then pushes it to the DB.

The code I have below displays correctly other than maybe formatting the number to have a , but that wouldn't be a necessity.

When I hit update I get Notice: Undefined variable: mileage in /var/www/html/Oil/cars.php on line 60

<link href="status.css" rel="stylesheet">

<meta name="viewport" content="width=device-width, initial-scale=1.0">
 <META HTTP-EQUIV="refresh" CONTENT="86400">

<?php
try {

    $db = new PDO("sqlite:/var/www/html/Oil/Vehicles.db");
    print "
";
    print "
Vehicle	Mileage	Filter Size	Oil Capacity	Oil Type	Change Date	New Miles	Update
";
    $result2 = $db->query('SELECT * FROM Cars');

    foreach ($result2 as $row) {

        print '
' . $row['vehicle'] .'	';
        print "" . $row['mileage'] . "	";
        print '' . $row['filter'] .'	';
        print '' . $row['oilCap'] .'	';
        print '' . $row['oilType'] .'	';
        print '' . $row['changeDate'] .'	';
    print '<form action="" method="POST"><input type="Text" name= "mileage"/><input type="hidden" name="vehicle" value="' .$row['vehicle']. '"/>	';
    print '<button class="btn btn-default" type="submit" name="update">Update</button></form>
';
    }
    print "
";

} catch (PDOException $e) {
    echo $e->getMessage();
}
if (isset($_POST['update'])) {
    ini_set('display_errors', 1);
    error_reporting(E_ALL);

    $mileage = $_POST['mileage'];
    print $mileage;
    $vehicle = $_POST['vehicle'];
    print $vehicle;
    $change = date("m/d/Y");
    print $change;

    $sql = "UPDATE cars SET mileage = :mileage, chageDate = :change WHERE vehicle = :vehicle";

    try{
            $db2 = new PDO("sqlite:/var/www/html/Oil/Vehicles.db");
        if (!($results = $db2->prepare($sql))){
            echo "Prepare failed: (" . $db->errorInfo() . ") " . $db->errorCode();
        }elseif (!$results->bindValue(':mileage', $mileage)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->bindValue(':change', $change)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->bindValue(':vehicle', $vehicle)){
            echo "Binding parameters failed: (" . $results->errorInfo() . ") " . $results->errorCode();
        }elseif (!$results->execute()) {
            echo "Execute failed:\n";
            print_r($results->errorInfo());
        }else{
            $count = $results ->rowCount();
            if($results ->rowCount() == 0)
                echo 'Error';
            else
                echo 'Changed!';
        }

        } catch (PDOException $e) {
            echo $e->getMessage();
        }

}

?>

Maybe I'm not passing mileage correctly?

Body:
In your code,

The line 59 and 60 as you said are:

$milage = $_POST['mileage'];
print $mileage;

You are assigning the value from form field to $milage, but you are trying to print a variable named $mileage. Check the spelling. They are different. So the variable you are trying to print is obviously undefined.

Change the code to,

$mileage= $_POST['mileage'];
print $mileage;

Eventhough, it's just a typo. It can cause lot of debug time. So, try to understand the error and the problem will be somewhere beside it or it will have some relation atleast.


问:
How to provide X11 with a wm_name for a Qt4 window?

Background

I am about to resolve another issue, which consists in reserving screen-space for a Qt Window on X11. For this i use PyQt4 and Python-Xlib.

Situation

The application i want to save screen space for is a frameless Qt Window, 25px high and screen-wide, it's a panel in fact. The simplified code looks like this:

```<code>import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
# this module i made myself (see below):
import myXwindow

class QtPanel(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        # here i explicitely name the window:
        self.setWindowTitle('QtPanel')
        self.resize(QtGui.QDesktopWidget().screenGeometry().width(), 25)
        self.move(0,0)
        self.setWindowFlags(QtCore.Qt.Widget |
        QtCore.Qt.FramelessWindowHint |
        QtCore.Qt.WindowStaysOnTopHint)
        self.setAttribute(QtCore.Qt.WA_X11NetWmWindowTypeDock)

    def main():
        app = QtGui.QApplication(sys.argv)
        panel = QtPanel()
        panel.show()
        xwindow = myXwindow.Window(str(panel.windowTitle()))
        sys.exit(app.exec_())

if __name__ == '__main__':
    main()
</code>```

Now to reserve space for this QtPanel application, i need to call on xlib. Here below i will just show how i intend to 'grab' my window from X. The following module is imported in the code here above to get the Xwindow of my panel:

```<code>from Xlib.display import Display
from Xlib import X

class Window(object):

    def __init__(self, title):

        self._title = title
        self._root = Display().screen().root
        self._window = self.find_window()

    def find_window(self):

        my_window = None
        display = Display()

        windowIDs = self._root.get_full_property(
                    display.intern_atom('_NET_CLIENT_LIST'),
                    X.AnyPropertyType).value

        print 'looking for windows:'
        count = 0
        for windowID in windowIDs:
            count += 1
            window = display.create_resource_object('window', windowID)
            title = window.get_wm_name()
            print 'window', count, ':', title
            if self._title in title:
                my_window = window

        return my_window
</code>```

Problem

Now when i run the QtPanel application, it should return a list of names of all the windows currently displayed by X. Despite having been named explicitly in the code (see here above) the QtPanel application either has no name (i.e. None or '') or is named 'x-nautilus-desktop', here is a sample of what was returned:

```<code>$ python ./Qtpanel.py
looking for windows:
window 1 : Bottom Expanded Edge Panel
window 2 : cairo-dock
window 3 : x-nautilus-desktop
window 4 : ReserveSpace - NetBeans IDE 6.9
window 5 : How to provide X11 with a wm_name for a Qt4 window? - Stack Overflow - Mozilla Firefox
</code>```

Question

How can i 'name' my Qt Application or Qt toplevel window so it shows properly on X?
And/or: how can i identify my application in X other than with the application's name?

答: Although i don't quite know what the unnamed window is (and it seems related to launching the QtPanel application, the Xlib script is not able to find the window on display because it is queried before the event loop QApplication._exec(). A thread may be required to do that outside of the main loop.</p>

Body:
Background

I am about to resolve another issue, which consists in reserving screen-space for a Qt Window on X11. For this i use PyQt4 and Python-Xlib.

Situation

The application i want to save screen space for is a frameless Qt Window, 25px high and screen-wide, it's a panel in fact. The simplified code looks like this:

import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
# this module i made myself (see below):
import myXwindow

class QtPanel(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        # here i explicitely name the window:
        self.setWindowTitle('QtPanel')
        self.resize(QtGui.QDesktopWidget().screenGeometry().width(), 25)
        self.move(0,0)
        self.setWindowFlags(QtCore.Qt.Widget |
        QtCore.Qt.FramelessWindowHint |
        QtCore.Qt.WindowStaysOnTopHint)
        self.setAttribute(QtCore.Qt.WA_X11NetWmWindowTypeDock)

    def main():
        app = QtGui.QApplication(sys.argv)
        panel = QtPanel()
        panel.show()
        xwindow = myXwindow.Window(str(panel.windowTitle()))
        sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Now to reserve space for this QtPanel application, i need to call on xlib. Here below i will just show how i intend to 'grab' my window from X. The following module is imported in the code here above to get the Xwindow of my panel:

from Xlib.display import Display
from Xlib import X

class Window(object):

    def __init__(self, title):

        self._title = title
        self._root = Display().screen().root
        self._window = self.find_window()

    def find_window(self):

        my_window = None
        display = Display()

        windowIDs = self._root.get_full_property(
                    display.intern_atom('_NET_CLIENT_LIST'),
                    X.AnyPropertyType).value

        print 'looking for windows:'
        count = 0
        for windowID in windowIDs:
            count += 1
            window = display.create_resource_object('window', windowID)
            title = window.get_wm_name()
            print 'window', count, ':', title
            if self._title in title:
                my_window = window

        return my_window

Problem

Now when i run the QtPanel application, it should return a list of names of all the windows currently displayed by X. Despite having been named explicitly in the code (see here above) the QtPanel application either has no name (i.e. None or '') or is named 'x-nautilus-desktop', here is a sample of what was returned:

$ python ./Qtpanel.py
looking for windows:
window 1 : Bottom Expanded Edge Panel
window 2 : cairo-dock
window 3 : x-nautilus-desktop
window 4 : ReserveSpace - NetBeans IDE 6.9
window 5 : How to provide X11 with a wm_name for a Qt4 window? - Stack Overflow - Mozilla Firefox

Question

How can i 'name' my Qt Application or Qt toplevel window so it shows properly on X?
And/or: how can i identify my application in X other than with the application's name?


问:
Mesh in some places looks unsmooth and glitched
So i'm modelling a face everything is great, then I look at the nose and boom.
What is it? Why this mesh looks like I don't know... not smooth or separated.
How can I fix that?

Here's the image:
nose problem

答:
enter edit mode.

Right-click on your object

click "shade smooth"

If you are still not satisfied, try experimenting with some textures.


问:
Django - How do I create custom permissions in DRF to restrict users from making API calls that they are not authorised to?
I am working on a web app that uses DRF as the backend and ReactJS as the frontend. My web app has users from different sales departments, and I would like to restrict the permission such that only the users from Sales Department A can see the sales projects that are tagged under Sales Department A, and if the users try to access a sales project page that they are not authorised to, it should return an error page. I tried googling for the answer, but I am not sure if the answer I found is the best solution for my problem. I saw solutions using Django Groups, but I was not sure how it works (so if someone could clarify it would be great!). I was hoping for a solution that would sort of have a check layer within the view or serializer, and from there would deduce which sales department the request.user is from, and hence whether or not the data should be released to them.

below is my models.py for more clarity on the structure i am using.

```<code>class UserProfile(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.ManyToManyField('SalesDepartment', related_name='users', blank=True)
    contact_number = PhoneNumberField(blank=True)
    email = models.EmailField(max_length=255)
    email_password = models.CharField(max_length=255)
    profile_picture = models.ImageField(upload_to='profile/', default='profile/blank.png')

    def __str__(self):
         return str(self.user.username)

class SalesDepartment(models.Model):
    department_id = models.AutoField(primary_key=True)
    department_name = models.CharField(max_length=100)

    def __str__(self):
         return self.department_name

class SalesProject(models.Model):

    sales_project_id = models.AutoField(primary_key=True)
    sales_project_name = models.CharField(max_length=100)
    creation_date = models.DateField(default=timezone.localdate)
    sales_department = models.ForeignKey('SalesDepartment', on_delete=models.CASCADE)

    def __str__(self):
        return self.sales_project_name
</code>```

The UserProfile model has a M2M field to the SalesDepartment model, and the SalesProject model has a Foreign Key relation to the SalesDepartment model. Hence, I am hoping to check for the user's sales department from the UserProfile model, and check to see if it is the same SalesDepartment as the one linked to the specific SalesProject that the API call is getting, and if so, return the response data as per usual, but if not, then return an error for the response data.

All help is appreciated, I am new to Django and DRF especially, hope that you guys would guide me to the correct path if I am misguided on how I am supposed to handle this authorisation problem. Thanks all in advance!

答:
```<code>from rest_framework import permissions

class IsTheUserYouWant(permissions.BasePermission):
    """
    Here I'm checking if the request.user, if the request is coming from a group that is
    allowed to perform this action or if the user here is an staff member, aka admin user.
    You can check whatever you want here since you have access to the user. So you  can
    check the sales_department like you mentioned in the question.
    """
    def has_permission(self, request, view):
        if request.user and request.user.groups.filter(name="Group You Created") or request.user.is_staff:
            return True
        return False
</code>```

Views.py example usage

```<code>class SalesProjectSet(viewsets.ModelViewSet):
    queryset = SalesProject.objects.all()
    serializer_class = SalesProjectSerializer
    permission_classes = [IsTheUserYouWant]
</code>```

In the Django Admin page you can create a Group and add users to it If you want, then you can check in the permission if the user is from the group who are allowed.

Body:
I am working on a web app that uses DRF as the backend and ReactJS as the frontend. My web app has users from different sales departments, and I would like to restrict the permission such that only the users from Sales Department A can see the sales projects that are tagged under Sales Department A, and if the users try to access a sales project page that they are not authorised to, it should return an error page. I tried googling for the answer, but I am not sure if the answer I found is the best solution for my problem. I saw solutions using Django Groups, but I was not sure how it works (so if someone could clarify it would be great!). I was hoping for a solution that would sort of have a check layer within the view or serializer, and from there would deduce which sales department the request.user is from, and hence whether or not the data should be released to them.

below is my models.py for more clarity on the structure i am using.

class UserProfile(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    department = models.ManyToManyField('SalesDepartment', related_name='users', blank=True)
    contact_number = PhoneNumberField(blank=True)
    email = models.EmailField(max_length=255)
    email_password = models.CharField(max_length=255)
    profile_picture = models.ImageField(upload_to='profile/', default='profile/blank.png')

    def __str__(self):
         return str(self.user.username)

class SalesDepartment(models.Model):
    department_id = models.AutoField(primary_key=True)
    department_name = models.CharField(max_length=100)

    def __str__(self):
         return self.department_name

class SalesProject(models.Model):

    sales_project_id = models.AutoField(primary_key=True)
    sales_project_name = models.CharField(max_length=100)
    creation_date = models.DateField(default=timezone.localdate)
    sales_department = models.ForeignKey('SalesDepartment', on_delete=models.CASCADE)

    def __str__(self):
        return self.sales_project_name

The UserProfile model has a M2M field to the SalesDepartment model, and the SalesProject model has a Foreign Key relation to the SalesDepartment model. Hence, I am hoping to check for the user's sales department from the UserProfile model, and check to see if it is the same SalesDepartment as the one linked to the specific SalesProject that the API call is getting, and if so, return the response data as per usual, but if not, then return an error for the response data.

All help is appreciated, I am new to Django and DRF especially, hope that you guys would guide me to the correct path if I am misguided on how I am supposed to handle this authorisation problem. Thanks all in advance!

Body:
from rest_framework import permissions

class IsTheUserYouWant(permissions.BasePermission):
    """
    Here I'm checking if the request.user, if the request is coming from a group that is
    allowed to perform this action or if the user here is an staff member, aka admin user.
    You can check whatever you want here since you have access to the user. So you  can
    check the sales_department like you mentioned in the question.
    """
    def has_permission(self, request, view):
        if request.user and request.user.groups.filter(name="Group You Created") or request.user.is_staff:
            return True
        return False

Views.py example usage

class SalesProjectSet(viewsets.ModelViewSet):
    queryset = SalesProject.objects.all()
    serializer_class = SalesProjectSerializer
    permission_classes = [IsTheUserYouWant]

In the Django Admin page you can create a Group and add users to it If you want, then you can check in the permission if the user is from the group who are allowed.


答:
Performant solution without using any loops or calling the function twice:</p>

```<code>$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$split = str_split(substr(str_shuffle($chars), 0, 32), 25);
$res = 'pro_sec_'.$split[0].'00'.$split[1];

echo $res; // pro_sec_c8s5iwyQY0nZoJf73EOkC9vqS00dNLWVKg
</code>```

Title: How to generate 34 alphanumerics with a pattern in PHP?

Body:
I want to generate 34 random letters (capitalized and not) and numbers. Before the generated 34 random alphanumerics there is a word pro_sec_ which is there everytime it generate. And the 25th & 26th is 00

So the generated result will be: (just an example)

pro_sec_Vy6Q67sh6HvP90j7gWnq6SxN00p8Gapu66

Another ex.
pro_sec_6B57nTshusbnay6esjabxns800nGvaz2Lov

The pro_sec_ and the 00 there in 25th and 26th are always the same and the rest are just generated.

Body:
Performant solution without using any loops or calling the function twice:

$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$split = str_split(substr(str_shuffle($chars), 0, 32), 25);
$res = 'pro_sec_'.$split[0].'00'.$split[1];

echo $res; // pro_sec_c8s5iwyQY0nZoJf73EOkC9vqS00dNLWVKg


问:
Using the predict function from R 'caret' package
I am trying to run the command below:

```<code>predDF <- data.frame(pred.RF, pred.SVM, pred.KNN, pred.NB, pred.BGM, pred.MARS, pred.GAM, pred.SGD, satisfied = pr.out.incl.score.val.2.df.x$satisfied)

modelStack1 <- train(satisfied ~ ., predDF, method = "glm")

testPredLevelOne <- data.frame(pred.RF.3, pred.SVM.3, pred.KNN.3, pred.NB.3, pred.BGM.3, pred.MARS.3, pred.GAM.3, pred.SGD.3, satisfied = pr.out.incl.score.val.3.df.x$satisfied)

combPred1 <- predict(modelStack1, testPredLevelOne)
</code>```

The data frame predDF has the 4888 observations (rows), and the data frame testPredLevelOne has 2632 observations (rows). From what I understand, this difference in the number of observations shouldn't matter when I execute combPred1 <- predict(modelStack1, testPredLevelOne). But when I execute the line, I am getting the error below:

```<code>Warning message:
'newdata' had 2632 rows but variables found have 4888 rows
</code>```

How can I solve this error?

For more reference, when I do str(testPredLevelOne), the output is below:

```<code> str(testPredLevelOne)
'data.frame':   2632 obs. of  9 variables:
 $ pred.RF.3  : Factor w/ 2 levels "0","1": 1 1 2 1 2 1 1 2 2 1 ...
 $ pred.SVM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.KNN.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 2 1 2 2 2 ...
 $ pred.NB.3  : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ pred.BGM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ pred.MARS.3: Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.GAM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.SGD.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ satisfied  : Factor w/ 2 levels "0","1": 1 1 2 1 2 1 1 1 1 1 ...
</code>```

Thank you,

答:
You need to provide the new data with similar column names as your train data. It is not like sklearn in python.

For example:

```<code>library(caret)
idx = sample(nrow(iris),100)
v1_train = iris$Sepal.Length[idx]
v2_train = iris$Sepal.Width[idx]
v3_train = iris$Petal.Length[idx]
y_train = iris$Petal.Width[idx]

v1_test = iris$Sepal.Length[-idx]
v2_test = iris$Sepal.Width[-idx]
v3_test = iris$Petal.Length[-idx]
y_test = iris$Petal.Width[-idx]

predDF <- data.frame(v1_train,v2_train,v3_train,y = y_train)
modelStack1 <- train(y ~ ., predDF, method = "glm")

testPredLevelOne <- data.frame(v1_test,v2_test,v3_test,y = y_test)
combPred1 <- predict(modelStack1, testPredLevelOne)

Warning message:
'newdata' had 50 rows but variables found have 100 rows
</code>```

We check the length and values of the prediction and it is simply that from the training:

```<code>length(combPred1)
[1] 100
table(combPred1 == modelStack1$finalModel$fitted.values)
TRUE
 100
</code>```

If we rename the column names of the test to the same as train data, it will not cause an error:

```<code>colnames(testPredLevelOne) = colnames(predDF)
combPred1 <- predict(modelStack1, testPredLevelOne)
 length(combPred1)
[1] 50
</code>```

Body:
I am trying to run the command below:

predDF <- data.frame(pred.RF, pred.SVM, pred.KNN, pred.NB, pred.BGM, pred.MARS, pred.GAM, pred.SGD, satisfied = pr.out.incl.score.val.2.df.x$satisfied)

modelStack1 <- train(satisfied ~ ., predDF, method = "glm")

testPredLevelOne <- data.frame(pred.RF.3, pred.SVM.3, pred.KNN.3, pred.NB.3, pred.BGM.3, pred.MARS.3, pred.GAM.3, pred.SGD.3, satisfied = pr.out.incl.score.val.3.df.x$satisfied)

combPred1 <- predict(modelStack1, testPredLevelOne)

The data frame predDF has the 4888 observations (rows), and the data frame testPredLevelOne has 2632 observations (rows). From what I understand, this difference in the number of observations shouldn't matter when I execute combPred1 <- predict(modelStack1, testPredLevelOne). But when I execute the line, I am getting the error below:

Warning message:
'newdata' had 2632 rows but variables found have 4888 rows

How can I solve this error?

For more reference, when I do str(testPredLevelOne), the output is below:

 str(testPredLevelOne)
'data.frame':   2632 obs. of  9 variables:
 $ pred.RF.3  : Factor w/ 2 levels "0","1": 1 1 2 1 2 1 1 2 2 1 ...
 $ pred.SVM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.KNN.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 2 1 2 2 2 ...
 $ pred.NB.3  : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ pred.BGM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ pred.MARS.3: Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.GAM.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 2 ...
 $ pred.SGD.3 : Factor w/ 2 levels "0","1": 1 1 2 2 2 1 1 2 2 1 ...
 $ satisfied  : Factor w/ 2 levels "0","1": 1 1 2 1 2 1 1 1 1 1 ...

Thank you,

Body:
You need to provide the new data with similar column names as your train data. It is not like sklearn in python.

For example:

library(caret)
idx = sample(nrow(iris),100)
v1_train = iris$Sepal.Length[idx]
v2_train = iris$Sepal.Width[idx]
v3_train = iris$Petal.Length[idx]
y_train = iris$Petal.Width[idx]

v1_test = iris$Sepal.Length[-idx]
v2_test = iris$Sepal.Width[-idx]
v3_test = iris$Petal.Length[-idx]
y_test = iris$Petal.Width[-idx]

predDF <- data.frame(v1_train,v2_train,v3_train,y = y_train)
modelStack1 <- train(y ~ ., predDF, method = "glm")

testPredLevelOne <- data.frame(v1_test,v2_test,v3_test,y = y_test)
combPred1 <- predict(modelStack1, testPredLevelOne)

Warning message:
'newdata' had 50 rows but variables found have 100 rows

We check the length and values of the prediction and it is simply that from the training:

length(combPred1)
[1] 100
table(combPred1 == modelStack1$finalModel$fitted.values)
TRUE
 100

If we rename the column names of the test to the same as train data, it will not cause an error:

colnames(testPredLevelOne) = colnames(predDF)
combPred1 <- predict(modelStack1, testPredLevelOne)
 length(combPred1)
[1] 50