问:
How to convert Double to String with exponential sign
I want to convert a Double to String with exponential signs in it.
For example, Double value is 4.4395749E7 after converting to String it should be 4.4395749E+07 (Same as how it shows in MS Excel).

I have tried double.toString(), but it is converting to 4.4395749E7:

```<code>Double doubleValue = 44395749d;
doubleValue.toString();
</code>```

Expected is 4.4395749E+07, but actual is 4.4395749E7.

答:
You can use DecimalFormat to format your number:

```<code>Double value = 44395749d;
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
if (value > 1 || value < -1) {
    symbols.setExponentSeparator("E+");
}
DecimalFormat decimalFormat = new DecimalFormat("0E00", symbols);
decimalFormat.setMaximumFractionDigits(Integer.MAX_VALUE);
System.out.println(decimalFormat.format(value));
</code>```

This uses DecimalFormatSymbols to add the + for the exponent if needed (value > 1 or value < -1). To get all fraction digits use setMaximumFractionDigits(Integer.MAX_VALUE). You can simply change the format if needed.

The result will be 4.4395749E+07.

Bare in mind to set a specific locale if needed:

```<code>DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.ENGLISH)
</code>```

Body:
I want to convert a Double to String with exponential signs in it.
For example, Double value is 4.4395749E7 after converting to String it should be 4.4395749E+07 (Same as how it shows in MS Excel).

I have tried double.toString(), but it is converting to 4.4395749E7:

Double doubleValue = 44395749d;
doubleValue.toString();

Expected is 4.4395749E+07, but actual is 4.4395749E7.

Body:
You can use DecimalFormat to format your number:

Double value = 44395749d;
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
if (value > 1 || value < -1) {
    symbols.setExponentSeparator("E+");
}
DecimalFormat decimalFormat = new DecimalFormat("0E00", symbols);
decimalFormat.setMaximumFractionDigits(Integer.MAX_VALUE);
System.out.println(decimalFormat.format(value));

This uses DecimalFormatSymbols to add the + for the exponent if needed (value > 1 or value < -1). To get all fraction digits use setMaximumFractionDigits(Integer.MAX_VALUE). You can simply change the format if needed.

The result will be 4.4395749E+07.

Bare in mind to set a specific locale if needed:

DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.ENGLISH)


来源: stackexchange

问:
Recursion to get maximum difference in array
Return a pair of numbers p and q in an array. p must appear before q in the array, and q-p must be the highest possible value

A=[1,4,12,5,9,1,3,8]

the return values would be p=1 & q=12

Someone suggested below solution.
However I am not sure what it should return in the 'third case' as suggested below:

Suggestion:

Divide A evenly into two smaller arrays A1,A2, and solve the problem (recursively) on A1 and A2. Can that help you find the optimum on A? Don't forget you're allowed to use extra processing costing up to O(n).Suppose that p,q is the optimal pair for A. Either p,q∈A1, or p,q∈A2, or neither of these cases is true. What can you say in the third case about p and q?

Below is my code where it basically divides the array and get the minimum from first half and maximum from second half. There is 0(n) solution for this but i am interested in the recursive one as i am learning the recursion. So please don't suggest any other solution.

```<code>    #define min_f(a, b) (a)>(b)?(b):(a)
    #define max_f(a, b) (a)>(b)?(a):(b)
    #define MAX 1 << 30
    #define MIN -1

    int get_min(int *a, int start, int end)
    {
            int t_min = MAX;
            while(start <= end) {
                    t_min = min_f(t_min, a[start]);
                    start++;
            }
            return t_min;
    }

    int get_max(int *a, int start, int end)
    {
            int t_max = MIN;
            while(start <= end) {
                    t_max = max_f(t_max, a[start]);
                    start++;
            }
            return t_max;
    }

    int foo(int *a, int start, int end)
    {
            int g_max = MIN;
            int min, max, i;

            for(i=0;i<=end;i++) {
                    min = get_min(a, start, i);
                    max = get_max(a, i+1, end);
                    if (max > min) {
                            g_max = max_f(g_max, max-min);
                    }
            }
            return g_max;
    }

    int main()
    {
            int a[] = {1,4,12,5,9,1,3,8};
            int size = sizeof(a)/sizeof(a[0]);
            printf("%d\n", foo(a, 0, size-1));
            return 0;
    }
</code>```

答:
Can find maximum value first in an recursion function, then find the minimum value at the same way. After you can find the differance. I don't think that you can make it by one function.</p>

```<code> public static int diff(int[] arr)
    {
        int max=findMax(arr, 0, arr.Length - 1);
        int min=findMin(arr, 0, arr.Length - 1);

        return max-min;
    }

 private static int findMax(int[] arr, int index_begin, int index_end)
    {
        if (index_begin == index_end) return arr[index_begin];

        int m = (index_begin + index_end) / 2;

        return Math.Max(findMax(arr, index_begin, m), findMax(arr, m + 1,
        index_end));
    }
 private static int findMin(int[] arr, int index_begin, int index_end)
    {
        if (index_begin == index_end) return arr[index_begin];

        int m = (index_begin + index_end) / 2;

        return Math.Min( findMin(arr, index_begin, m), findMin(arr, m + 1,
        index_end));
    }
</code>```

ContentLicense: CC BY-SA 3.0

Body:
Return a pair of numbers p and q in an array. p must appear before q in the array, and q-p must be the highest possible value

A=[1,4,12,5,9,1,3,8]

the return values would be p=1 & q=12

Someone suggested below solution.
However I am not sure what it should return in the 'third case' as suggested below:

Suggestion:

Divide A evenly into two smaller arrays A1,A2, and solve the problem (recursively) on A1 and A2. Can that help you find the optimum on A? Don't forget you're allowed to use extra processing costing up to O(n).Suppose that p,q is the optimal pair for A. Either p,q∈A1, or p,q∈A2, or neither of these cases is true. What can you say in the third case about p and q?

Below is my code where it basically divides the array and get the minimum from first half and maximum from second half. There is 0(n) solution for this but i am interested in the recursive one as i am learning the recursion. So please don't suggest any other solution.

    #define min_f(a, b) (a)>(b)?(b):(a)
    #define max_f(a, b) (a)>(b)?(a):(b)
    #define MAX 1 << 30
    #define MIN -1

    int get_min(int *a, int start, int end)
    {
            int t_min = MAX;
            while(start <= end) {
                    t_min = min_f(t_min, a[start]);
                    start++;
            }
            return t_min;
    }

    int get_max(int *a, int start, int end)
    {
            int t_max = MIN;
            while(start <= end) {
                    t_max = max_f(t_max, a[start]);
                    start++;
            }
            return t_max;
    }

    int foo(int *a, int start, int end)
    {
            int g_max = MIN;
            int min, max, i;

            for(i=0;i<=end;i++) {
                    min = get_min(a, start, i);
                    max = get_max(a, i+1, end);
                    if (max > min) {
                            g_max = max_f(g_max, max-min);
                    }
            }
            return g_max;
    }

    int main()
    {
            int a[] = {1,4,12,5,9,1,3,8};
            int size = sizeof(a)/sizeof(a[0]);
            printf("%d\n", foo(a, 0, size-1));
            return 0;
    }

Body:
Can find maximum value first in an recursion function, then find the minimum value at the same way. After you can find the differance. I don't think that you can make it by one function.

 public static int diff(int[] arr)
    {
        int max=findMax(arr, 0, arr.Length - 1);
        int min=findMin(arr, 0, arr.Length - 1);

        return max-min;
    }

 private static int findMax(int[] arr, int index_begin, int index_end)
    {
        if (index_begin == index_end) return arr[index_begin];

        int m = (index_begin + index_end) / 2;

        return Math.Max(findMax(arr, index_begin, m), findMax(arr, m + 1,
        index_end));
    }
 private static int findMin(int[] arr, int index_begin, int index_end)
    {
        if (index_begin == index_end) return arr[index_begin];

        int m = (index_begin + index_end) / 2;

        return Math.Min( findMin(arr, index_begin, m), findMin(arr, m + 1,
        index_end));
    }

ContentLicense: CC BY-SA 4.0


问:
Node.js Body-Parser not able to retrieve form input
I am trying to console.log a input from a form. However, the body-parser is showing 'undefined' for the input I am trying to print on my terminal. I am not sure what I did incorrect.
Please advise what I did wrong. Thank You.

HTML form

```<code><html>
<header>
    <link rel="stylesheet" type="text/css" href="css/form.css">
</header>
<body>
<form id="form" class="topBefore" action="/form" method="post" enctype="multipart/form-data">
              <input id="name" name="name" type="text" placeholder="NAME">
              <input id="email" name="email" type="text" placeholder="E-MAIL">
              <textarea id="message" name ="message" type="text" placeholder="MESSAGE"></textarea>
              <input type="file" name="upload" multiple>
      <input id="submit" type="submit" value="GO!">
    </form>
</body>
</html>
</code>```

App.js

```<code>// port and modules
var port = 3000;
var express = require('express');
var http = require('http');
var path = require('path');
var formidable = require('formidable');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var fs = require('fs');
var app = express();
// static resource folder (public)
app.use(express.static(path.join(__dirname, 'public')));

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/form', function(req, res){
    res.sendFile(__dirname + "/public/form.html");
});

app.post('/form', function(req, res)
{   //get form input
    var name = req.body.name;
    var email = req.body.email;
    var message = req.body.message;
    console.log(req.body.name);
    //upload file and save to directory
    var form = new formidable.IncomingForm();
    form.parse(req);
    //set upload path
    form.on('fileBegin', function (name, file){
        file.path = __dirname + '/public/icons/' + file.name;
        console.log(file.path);
    });
    //upload process
    form.on('file', function (name, file){
        console.log('Uploaded ' + file.name);

    });
    // redirect to home page after form submission
    res.redirect('/');
});

// connect to server and listen port
// index.html will be home page
http.createServer(app).listen(port, function(){
    console.log("{ server connection : success }");
});

//Database setup
mongoose.connect('mongodb://localhost/mydb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('{ database connection : success}');
});
</code>```

答:
Your form is multipart, so the req.body cannot retrieve data that is sent from the HTML form. You need to use Multer, it is explained here: https://www.npmjs.com/package/multer

In summary, to handle request from multer. You need to provide configuration to the multer object. Here is a code example, this code takes the request in singleFileUpload and run the upload function. The upload function handles the request through multer configuration. If you want to retrieve data, then you can access it through the request function inside the multer.diskStorage.

Let me know if you want clarifications.

```<code>`var storage = multer.diskStorage({
   destination: function(req, file, cb) {
   cb(null, "public/uploaded_files");
   },
   filename: function(req, file, cb) {
    cb(null, req.files[0].fieldname);
   }
 });
var upload = multer({ storage: storage }).any();
function singleFileUpload(req, res) {
upload(req, res, err => {
 if (err instanceof multer.MulterError) {
   return res.status(500).json(err);
  } else if (err) {
   return res.status(500).json(err);
  }
 return res.status(200).send(req.file);
});
}`
</code>```

Body:
I am trying to console.log a input from a form. However, the body-parser is showing 'undefined' for the input I am trying to print on my terminal. I am not sure what I did incorrect.
Please advise what I did wrong. Thank You.

HTML form

    <link rel="stylesheet" type="text/css" href="css/form.css">

<form id="form" class="topBefore" action="/form" method="post" enctype="multipart/form-data">
              <input id="name" name="name" type="text" placeholder="NAME">
              <input id="email" name="email" type="text" placeholder="E-MAIL">
              <textarea id="message" name ="message" type="text" placeholder="MESSAGE"></textarea>
              <input type="file" name="upload" multiple>
      <input id="submit" type="submit" value="GO!">
    </form>

App.js

// port and modules
var port = 3000;
var express = require('express');
var http = require('http');
var path = require('path');
var formidable = require('formidable');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var fs = require('fs');
var app = express();
// static resource folder (public)
app.use(express.static(path.join(__dirname, 'public')));

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.get('/form', function(req, res){
    res.sendFile(__dirname + "/public/form.html");
});

app.post('/form', function(req, res)
{   //get form input
    var name = req.body.name;
    var email = req.body.email;
    var message = req.body.message;
    console.log(req.body.name);
    //upload file and save to directory
    var form = new formidable.IncomingForm();
    form.parse(req);
    //set upload path
    form.on('fileBegin', function (name, file){
        file.path = __dirname + '/public/icons/' + file.name;
        console.log(file.path);
    });
    //upload process
    form.on('file', function (name, file){
        console.log('Uploaded ' + file.name);

    });
    // redirect to home page after form submission
    res.redirect('/');
});

// connect to server and listen port
// index.html will be home page
http.createServer(app).listen(port, function(){
    console.log("{ server connection : success }");
});

//Database setup
mongoose.connect('mongodb://localhost/mydb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function() {
  console.log('{ database connection : success}');
});

Body:
Your form is multipart, so the req.body cannot retrieve data that is sent from the HTML form. You need to use Multer, it is explained here: https://www.npmjs.com/package/multer

In summary, to handle request from multer. You need to provide configuration to the multer object. Here is a code example, this code takes the request in singleFileUpload and run the upload function. The upload function handles the request through multer configuration. If you want to retrieve data, then you can access it through the request function inside the multer.diskStorage.

Let me know if you want clarifications.

`var storage = multer.diskStorage({
   destination: function(req, file, cb) {
   cb(null, "public/uploaded_files");
   },
   filename: function(req, file, cb) {
    cb(null, req.files[0].fieldname);
   }
 });
var upload = multer({ storage: storage }).any();
function singleFileUpload(req, res) {
upload(req, res, err => {
 if (err instanceof multer.MulterError) {
   return res.status(500).json(err);
  } else if (err) {
   return res.status(500).json(err);
  }
 return res.status(200).send(req.file);
});
}`


问:
why is this command not executing with a TFS build?
I have 2 powershell scripts

script1.ps1 contains REST calls to Vault, which returns a json response containing some keys/values.

```<code>Function getValues($token) {
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("X-Vault-Token", $token)
    $response = Invoke-RestMethod  -method GET -uri "https://vault.com:8243/v1/secret/vault/development" -ContentType 'application/json' -headers $headers
    $response.data| ConvertTo-Json  -depth 100
}
getValues $token
</code>```

suppose one of those keys in the response is as follows:

```<code>key1:value123
</code>```

script2.ps1 calls scrip1.ps1 like this

```<code>$currentDirectory = "D:\\Scripts"
$response = & "$currentDirectory\script1.ps1" | ConvertFrom-Json
$pass = $response[1]."key1"
$pass
</code>```

that block executes just fine if i am testing locally and i get value123 as output as expected

now i set up a WinRM remote powershell task on TFS as part of the build which is calling script2.ps1.

of course i am logging pretty much everything to a log file in my script2 so i can see all the output happpening, except the response. the response is not being returned whatsoever!

$pass is not printing anything back when i run the TFS build, but locally it prints just fine

is there something special i have to wrap this command with for TFS specifically? am i missing something here??

答:
I figured out the issue finally

We had the token saved in USER environment variables that the script was not able to call from. I think when I was testing because I was logged on on the server as said user, the script worked because it recognized the user and was able to fetch the environment variable.

However, when I am running from TFS using remote Powershell, its not recognizing the user env variable.

Setting the env variable token in SYSTEM env variables worked!

Body:
I have 2 powershell scripts

script1.ps1 contains REST calls to Vault, which returns a json response containing some keys/values.

Function getValues($token) {
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("X-Vault-Token", $token)
    $response = Invoke-RestMethod  -method GET -uri "https://vault.com:8243/v1/secret/vault/development" -ContentType 'application/json' -headers $headers
    $response.data| ConvertTo-Json  -depth 100
}
getValues $token

suppose one of those keys in the response is as follows:

key1:value123

script2.ps1 calls scrip1.ps1 like this

$currentDirectory = "D:\\Scripts"
$response = & "$currentDirectory\script1.ps1" | ConvertFrom-Json
$pass = $response[1]."key1"
$pass

that block executes just fine if i am testing locally and i get value123 as output as expected

now i set up a WinRM remote powershell task on TFS as part of the build which is calling script2.ps1.

of course i am logging pretty much everything to a log file in my script2 so i can see all the output happpening, except the response. the response is not being returned whatsoever!

$pass is not printing anything back when i run the TFS build, but locally it prints just fine

is there something special i have to wrap this command with for TFS specifically? am i missing something here??


问:
How to interact with the elements within #shadow-root (open) while Clearing Browsing Data of Chrome Browser using cssSelector
I had been following the discussion How to automate shadow DOM elements using selenium? to work with #shadow-root (open) elements.

While in the process of locating the Clear data button within the Clear browsing data popup, which appears while accessing the url chrome://settings/clearBrowserData through Selenium I am unable to locate the following element:

```<code>#shadow-root (open)
<settings-privacy-page>
</code>```

Snapshot:

Using Selenium following are my code trials and the associated errors encountered:

Attempt 1:

```<code>WebElement root5 = shadow_root4.findElement(By.tagName("settings-privacy-page"));
</code>```

Error:

```<code>Exception in thread "main" org.openqa.selenium.JavascriptException: javascript error: b.getElementsByTagName is not a function
</code>```

Attempt 2:

```<code>WebElement root5 = shadow_root4.findElement(By.cssSelector("settings-privacy-page"));
</code>```

Error:

```<code>Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"settings-privacy-page"}
</code>```

Attempt 3:

```<code>WebElement root5 = (WebElement)((JavascriptExecutor)shadow_root4).executeScript("return document.getElementsByTagName('settings-privacy-page')[0]");
</code>```

Error:

```<code>Exception in thread "main" java.lang.ClassCastException: org.openqa.selenium.remote.RemoteWebElement cannot be cast to org.openqa.selenium.JavascriptExecutor
</code>```

Incase if it is helpful the initial code block (till the above line) works perfect:

```<code>driver.get("chrome://settings/clearBrowserData");
WebElement root1 = driver.findElement(By.tagName("settings-ui"));
WebElement shadow_root1 = expand_shadow_element(root1);

WebElement root2 = shadow_root1.findElement(By.cssSelector("settings-main#main"));
WebElement shadow_root2 = expand_shadow_element(root2);

WebElement root3 = shadow_root2.findElement(By.cssSelector("settings-basic-page[role='main']"));
WebElement shadow_root3 = expand_shadow_element(root3);

WebElement root4 = shadow_root3.findElement(By.cssSelector("settings-section[page-title='Privacy and security']"));
WebElement shadow_root4 = expand_shadow_element(root4);
</code>```

PS: expand_shadow_element() works flawless.

答:
If you are trying to get 'Clear Data' element then you can use the below js to get the element and then perform.

```<code>return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')
</code>```

Here is the sample script.

```<code>driver.get("chrome://settings/clearBrowserData");
driver.manage().window().maximize();
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
// now you can click on clear data button
clearData.click();
</code>```

Edit 2: Explanation

Problem: Selenium does not provide explicit support to work with Shadow DOM elements, as they are not in the current dom. That's the reason why we will get NoSuchElementException exception when try to access the elements in the shadow dom.

Shadow DOM:

Note: We will be referring to the terms shown in the picture. So please go through the picture for better understanding.

Solution:

In order to work with shadow element first we have to find the shadow host to which the shadow dom is attached. Here is the simple method to get the shadow root based on the shadowHost.

```<code>private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}
</code>```

And then you can access the shadow tree element using the shadowRoot Element.

```<code>// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));
</code>```

In order to simplify all the above steps created the below method.

```<code>public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
    WebElement shardowRoot = getShadowRoot(driver, shadowHost);
    return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}
</code>```

Now you can get the shadowTree Element with single method call

```<code>WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");
</code>```

And perform the operations as usual like .click(), .getText().

```<code>shadowTreeElement.click()
</code>```

This Looks simple when you have only one level of shadow DOM. But here, in this case we have multiple levels of shadow doms. So we have to access the element by reaching each shadow host and root.

Below is the snippet using the methods that mentioned above (getShadowElement and getShadowRoot)

```<code>// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("settings-ui"));

// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "settings-main");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"settings-basic-page");
WebElement shadowElementL3 = getShadowElement(driver, shadowElementL2,"settings-section > settings-privacy-page");
WebElement shadowElementL4 = getShadowElement(driver, shadowElementL3,"settings-clear-browsing-data-dialog");
WebElement shadowElementL5 = getShadowElement(driver, shadowElementL4,"#clearBrowsingDataDialog");
WebElement clearData = shadowElementL5.findElement(By.cssSelector("#clearBrowsingDataConfirm"));
System.out.println(clearData.getText());
clearData.click();
</code>```

You can achieve all the above steps in single js call as at mentioned at the beginning of the answer (added below just to reduce the confusion).

```<code>WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
</code>```

Screenshot:

Body:
I had been following the discussion How to automate shadow DOM elements using selenium? to work with #shadow-root (open) elements.

While in the process of locating the Clear data button within the Clear browsing data popup, which appears while accessing the url chrome://settings/clearBrowserData through Selenium I am unable to locate the following element:

#shadow-root (open)
<settings-privacy-page>

Snapshot:

Using Selenium following are my code trials and the associated errors encountered:

Attempt 1:

WebElement root5 = shadow_root4.findElement(By.tagName("settings-privacy-page"));

Error:

Exception in thread "main" org.openqa.selenium.JavascriptException: javascript error: b.getElementsByTagName is not a function

Attempt 2:

WebElement root5 = shadow_root4.findElement(By.cssSelector("settings-privacy-page"));

Error:

Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"settings-privacy-page"}

Attempt 3:

WebElement root5 = (WebElement)((JavascriptExecutor)shadow_root4).executeScript("return document.getElementsByTagName('settings-privacy-page')[0]");

Error:

Exception in thread "main" java.lang.ClassCastException: org.openqa.selenium.remote.RemoteWebElement cannot be cast to org.openqa.selenium.JavascriptExecutor

Incase if it is helpful the initial code block (till the above line) works perfect:

driver.get("chrome://settings/clearBrowserData");
WebElement root1 = driver.findElement(By.tagName("settings-ui"));
WebElement shadow_root1 = expand_shadow_element(root1);

WebElement root2 = shadow_root1.findElement(By.cssSelector("settings-main#main"));
WebElement shadow_root2 = expand_shadow_element(root2);

WebElement root3 = shadow_root2.findElement(By.cssSelector("settings-basic-page[role='main']"));
WebElement shadow_root3 = expand_shadow_element(root3);

WebElement root4 = shadow_root3.findElement(By.cssSelector("settings-section[page-title='Privacy and security']"));
WebElement shadow_root4 = expand_shadow_element(root4);

PS: expand_shadow_element() works flawless.

Body:
If you are trying to get 'Clear Data' element then you can use the below js to get the element and then perform.

return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')

Here is the sample script.

driver.get("chrome://settings/clearBrowserData");
driver.manage().window().maximize();
JavascriptExecutor js = (JavascriptExecutor) driver;
WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");
// now you can click on clear data button
clearData.click();

Edit 2: Explanation

Problem: Selenium does not provide explicit support to work with Shadow DOM elements, as they are not in the current dom. That's the reason why we will get NoSuchElementException exception when try to access the elements in the shadow dom.

Shadow DOM:

Note: We will be referring to the terms shown in the picture. So please go through the picture for better understanding.

Solution:

In order to work with shadow element first we have to find the shadow host to which the shadow dom is attached. Here is the simple method to get the shadow root based on the shadowHost.

private static WebElement getShadowRoot(WebDriver driver,WebElement shadowHost) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    return (WebElement) js.executeScript("return arguments[0].shadowRoot", shadowHost);
}

And then you can access the shadow tree element using the shadowRoot Element.

// get the shadowHost in the original dom using findElement
WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS"));
// get the shadow root
WebElement shadowRoot = getShadowRoot(driver,shadowHost);
// access shadow tree element
WebElement shadowTreeElement = shadowRoot.findElement(By.cssSelector("shadow_tree_element_css"));

In order to simplify all the above steps created the below method.

public static WebElement getShadowElement(WebDriver driver,WebElement shadowHost, String cssOfShadowElement) {
    WebElement shardowRoot = getShadowRoot(driver, shadowHost);
    return shardowRoot.findElement(By.cssSelector(cssOfShadowElement));
}

Now you can get the shadowTree Element with single method call

WebElement shadowHost = driver.findElement(By.cssSelector("shadowHost_CSS_Goes_here));
WebElement shadowTreeElement = getShadowElement(driver,shadowHost,"shadow_tree_element_css");

And perform the operations as usual like .click(), .getText().

shadowTreeElement.click()

This Looks simple when you have only one level of shadow DOM. But here, in this case we have multiple levels of shadow doms. So we have to access the element by reaching each shadow host and root.

Below is the snippet using the methods that mentioned above (getShadowElement and getShadowRoot)

// Locate shadowHost on the current dom
WebElement shadowHostL1 = driver.findElement(By.cssSelector("settings-ui"));

// now locate the shadowElement by traversing all shadow levels
WebElement shadowElementL1 = getShadowElement(driver, shadowHostL1, "settings-main");
WebElement shadowElementL2 = getShadowElement(driver, shadowElementL1,"settings-basic-page");
WebElement shadowElementL3 = getShadowElement(driver, shadowElementL2,"settings-section > settings-privacy-page");
WebElement shadowElementL4 = getShadowElement(driver, shadowElementL3,"settings-clear-browsing-data-dialog");
WebElement shadowElementL5 = getShadowElement(driver, shadowElementL4,"#clearBrowsingDataDialog");
WebElement clearData = shadowElementL5.findElement(By.cssSelector("#clearBrowsingDataConfirm"));
System.out.println(clearData.getText());
clearData.click();

You can achieve all the above steps in single js call as at mentioned at the beginning of the answer (added below just to reduce the confusion).

WebElement clearData = (WebElement) js.executeScript("return document.querySelector('settings-ui').shadowRoot.querySelector('settings-main').shadowRoot.querySelector('settings-basic-page').shadowRoot.querySelector('settings-section > settings-privacy-page').shadowRoot.querySelector('settings-clear-browsing-data-dialog').shadowRoot.querySelector('#clearBrowsingDataDialog').querySelector('#clearBrowsingDataConfirm')");

Screenshot:


问:
Add attachment via VBA in MS Access
One of my form is as follows

It is a form made in MS Access which allows my users to add observations. An observation may include attachments as shown. I am able to click on attachment control and Add attachments to the popup that pops up. However, what is expected is that when I click ADD button as shown in the form above, this attachments shall be added to the corresponding field of a table.

All controls on this form are unbound.

The code written behind ADD button is as follows:

```<code>Private Sub cmdAdd_Click()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset

    Set db = CurrentDb
    Set rs = db.OpenRecordset("tblObservation", dbOpenDynaset)

    rs.AddNew

    rs![Artifact] = artifactId
    rs![Observation Text] = txtObservationText.Value

    'rs![Attachments] = ' not able to solve this

    rs.Update
    rs.Close

    Set rs = Nothing
    Set db = Nothing
End Sub
</code>```

答:
You can use the following reference from Microsoft

The relevant piece of code is this:

```<code>'  Instantiate the parent recordset.
Set rsEmployees = db.OpenRecordset("Employees")

'… Code to move to desired employee

' Activate edit mode.
rsEmployees.Edit

' Instantiate the child recordset.
Set rsPictures = rsEmployees.Fields("Pictures").Value

' Add a new attachment.
rsPictures.AddNew
rsPictures.Fields("FileData").LoadFromFile "EmpPhoto39392.jpg"
rsPictures.Update

' Update the parent record
rsEmployees.Update
</code>```

Title: Add attachment via VBA in MS Access

Body:
One of my form is as follows

It is a form made in MS Access which allows my users to add observations. An observation may include attachments as shown. I am able to click on attachment control and Add attachments to the popup that pops up. However, what is expected is that when I click ADD button as shown in the form above, this attachments shall be added to the corresponding field of a table.

All controls on this form are unbound.

The code written behind ADD button is as follows:

Private Sub cmdAdd_Click()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset

    Set db = CurrentDb
    Set rs = db.OpenRecordset("tblObservation", dbOpenDynaset)

    rs.AddNew

    rs![Artifact] = artifactId
    rs![Observation Text] = txtObservationText.Value

    'rs![Attachments] = ' not able to solve this

    rs.Update
    rs.Close

    Set rs = Nothing
    Set db = Nothing
End Sub

Body:
You can use the following reference from Microsoft

The relevant piece of code is this:

'  Instantiate the parent recordset.
Set rsEmployees = db.OpenRecordset("Employees")

'… Code to move to desired employee

' Activate edit mode.
rsEmployees.Edit

' Instantiate the child recordset.
Set rsPictures = rsEmployees.Fields("Pictures").Value

' Add a new attachment.
rsPictures.AddNew
rsPictures.Fields("FileData").LoadFromFile "EmpPhoto39392.jpg"
rsPictures.Update

' Update the parent record
rsEmployees.Update


问:
Copy value of above row in 1st column for rows matching pattern
Suppose I have a | separated text file like this:

```<code>123|col 2 row 1|col 3 row 1
xxx|col 2 row 2|col 3 row 2
xxx|col 2 row 3|col 3 row 3
789|col 2 row 4|col 3 row 4
xxx|col 2 row 5|col 3 row 5
xxx|col 2 row 6|col 3 row 6
</code>```

Using sed or awk how to get this:

```<code>123|col 2 row 1|col 3 row 1
123|col 2 row 2|col 3 row 2
123|col 2 row 3|col 3 row 3
789|col 2 row 4|col 3 row 4
789|col 2 row 5|col 3 row 5
789|col 2 row 6|col 3 row 6
</code>```

If value of column 1 is 'xxx' it should be replaced with value in above row.

答:
This might work for you (GNU sed):

```<code>sed -E 'N;s/^(([^|]*).*\n)xxx/\1\2/;P;D' file
</code>```

Append the next line to the current line and if that appended line begins xxx replace that string by the first field of the current line. Print/delete the current line and repeat.

Body:
Suppose I have a | separated text file like this:

123|col 2 row 1|col 3 row 1
xxx|col 2 row 2|col 3 row 2
xxx|col 2 row 3|col 3 row 3
789|col 2 row 4|col 3 row 4
xxx|col 2 row 5|col 3 row 5
xxx|col 2 row 6|col 3 row 6

Using sed or awk how to get this:

123|col 2 row 1|col 3 row 1
123|col 2 row 2|col 3 row 2
123|col 2 row 3|col 3 row 3
789|col 2 row 4|col 3 row 4
789|col 2 row 5|col 3 row 5
789|col 2 row 6|col 3 row 6

If value of column 1 is 'xxx' it should be replaced with value in above row.

Body:
This might work for you (GNU sed):

sed -E 'N;s/^(([^|]*).*\n)xxx/\1\2/;P;D' file

Append the next line to the current line and if that appended line begins xxx replace that string by the first field of the current line. Print/delete the current line and repeat.


问:
HTML <textarea> not working with Grammarly - overlapping another div
Strange one.
I've a very simple webpage for testing. Code below.
I get the resulting issue with teh Grammarly G icons not in the textareas. This happens when you need to scroll up and down the screen. As soon as you scroll, they move out of the textareas and overlap a div below.

```<code><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>

<body>
<div id="report" style="border: red solid thin">
<table width="100%" cellpadding="5">
    <tr>
        <td style="border:thin black solid;">
        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY1</textarea>
        </td>
    </tr>
    <tr>
        <td style="border:thin black solid;">
        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY2</textarea>
        </td>
    </tr>
    <tr>
        <td style="border:thin black solid;">
        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY3</textarea>
        </td>
    </tr>
    <tr>
        <td style="border:thin black solid;">
        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY4</textarea>
        </td>
    </tr>
</table>
</div>

<div id="menu" style="text-align: center; border: thin blue solid; ">
Test<br/>
Test<br/>
Test<br/>
Test<br/>
Test<br/>
Test<br/>
Test<br/>
Test<br/>
Test<br/>
</div>

</body>
</html>
</code>```

The result when I scroll is this
reult

答:
Setting out like this works... </p>

```<code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
</html>
</code>```

Body:
Strange one.
I've a very simple webpage for testing. Code below.
I get the resulting issue with teh Grammarly G icons not in the textareas. This happens when you need to scroll up and down the screen. As soon as you scroll, they move out of the textareas and overlap a div below.

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY1</textarea>

        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY2</textarea>

        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY3</textarea>

        <textarea rows="10" cols="80">TESTING AN ISSUE. WILL BE BACK ONLINE SHORTLY4</textarea>

Test

Test

Test

Test

Test

Test

Test

Test

Test

The result when I scroll is this
reult

Body:
Setting out like this works...

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
</html>


问:
How to fix ModuleNotFoundError when uploading virtualenv to IBM Cloud Functions?
I'm trying to upload a function to IBM Cloud Functions with a virtualenv that has opencv installed. However, when I try to run the action in IBM Cloud it says:

```<code>{
  "error": "Traceback (most recent call last):
File \"/action/1/src/exec__.py\", line 43, in <module>
from main__ import main as main
File \"/action/1/src/main__.py\", line 1, in <module>
import requests, base64, json, cv2\nModuleNotFoundError: No module named 'cv2'"
}
</code>```

I'm using the python:3.7 runtime for this. I thought this was a library issue since this runtime uses Debian Stretch and I've had problems importing opencv with the python:3-slim-strech docker image before since it didn't have some required libraries like libsm6, libxext6 and libxrender.

However, when I ran apt list in the docker image that IBM uses for its python:3.7 runtime, it had those libraries included.

I created the virtualenv using the docker method shown here. The exact command I used was the following:

```<code>docker run --rm -v "$PWD:/tmp" ibmfunctions/action-python-v3.7 /bin/bash -c
"cd tmp; virtualenv virtualenv; source virtualenv/bin/activate;
pip install --no-deps opencv-python;"
</code>```

I used --no-deps because the runtime already has numpy installed, which is the only dependency of opencv and because with numpy included the zip file exceeded the 48MB limit to upload it to Cloud Functions.

I should be able to import cv2 with no problems but I still get the previous message. Any help would be great!

答:
Using a virtualenv folder to include local packages does not automatically inherit the global site-packages from the runtime. This can be enabled using the --system-site-packages flag when using the virtualenv command.

Change the Docker command to the following to make this work:

```<code>docker run --rm -v "$PWD:/tmp" ibmfunctions/action-python-v3.7 /bin/bash -c
"cd tmp; virtualenv --system-site-packages virtualenv; source virtualenv/bin/activate;
pip install opencv-python;"
</code>```

--no-deps is no longer needed as the numpy dependency is already satisfied by the global site-package.

Following your commands with this updated Docker script now works for me.

Make sure you allocate enough memory to the OpenWhisk action. I had issues running the code with the default 256MB memory limit. Increasing this to 1024MB fixed any issues I encountered.

Body:
I'm trying to upload a function to IBM Cloud Functions with a virtualenv that has opencv installed. However, when I try to run the action in IBM Cloud it says:

{
  "error": "Traceback (most recent call last):
File \"/action/1/src/exec__.py\", line 43, in <module>
from main__ import main as main
File \"/action/1/src/main__.py\", line 1, in <module>
import requests, base64, json, cv2\nModuleNotFoundError: No module named 'cv2'"
}

I'm using the python:3.7 runtime for this. I thought this was a library issue since this runtime uses Debian Stretch and I've had problems importing opencv with the python:3-slim-strech docker image before since it didn't have some required libraries like libsm6, libxext6 and libxrender.

However, when I ran apt list in the docker image that IBM uses for its python:3.7 runtime, it had those libraries included.

I created the virtualenv using the docker method shown here. The exact command I used was the following:

docker run --rm -v "$PWD:/tmp" ibmfunctions/action-python-v3.7 /bin/bash -c
"cd tmp; virtualenv virtualenv; source virtualenv/bin/activate;
pip install --no-deps opencv-python;"

I used --no-deps because the runtime already has numpy installed, which is the only dependency of opencv and because with numpy included the zip file exceeded the 48MB limit to upload it to Cloud Functions.

I should be able to import cv2 with no problems but I still get the previous message. Any help would be great!

Body:
Using a virtualenv folder to include local packages does not automatically inherit the global site-packages from the runtime. This can be enabled using the --system-site-packages flag when using the virtualenv command.

Change the Docker command to the following to make this work:

docker run --rm -v "$PWD:/tmp" ibmfunctions/action-python-v3.7 /bin/bash -c
"cd tmp; virtualenv --system-site-packages virtualenv; source virtualenv/bin/activate;
pip install opencv-python;"

--no-deps is no longer needed as the numpy dependency is already satisfied by the global site-package.

Following your commands with this updated Docker script now works for me.

Make sure you allocate enough memory to the OpenWhisk action. I had issues running the code with the default 256MB memory limit. Increasing this to 1024MB fixed any issues I encountered.


问:
Angular *ngIf for nested formgroup value
I want to implement *ngIf for some div...

Doesn't work:

```<code>*ngIf="postForm.value.osnovne.sekcija === vozila"
</code>```

also

```<code>*ngIf="postForm.controls['osnovne'].value.sekcija === vozila
</code>```

This is my form:

```<code>this.postForm = this.fb.group({
      osnovne: this.fb.group({
        sekcija: vozila,
        cena: "",
        dogovor: "",
        opis: ""
      }),
      detaljne: this.fb.group({
        name: "",
        value: ""
      }),
      imagePath: this.fb.group({
        data: ""
      })
    });
</code>```

How to to that?

答:
Using ngx-sub-form library it'd be easier to break down your form into sub form components and it'd look like the following:

```<code><form [formGroup]="formGroup">
    <app-osnovne-form [formControlName]="formControlNames.osnovne"></app-osnovne-form>
</form>

<div *ngIf="formGroupValues.osnovne?.sekcija === 'vozila'; else noVozila">
  "vozila" is the current value of osnovne.sekcija
</div>

<ng-template #noVozila>
  "vozila" is not the current value of osnovne.sekcija
</ng-template>

```{{ formGroupValues | json }}```
</code>```

Here's a live demo: https://stackblitz.com/edit/so-answer-angular-ngif-for-nested-formgroup-value?file=src/app/form/form.component.html

Edit:

If you want to go further, I've just published a blog post to explain a lot of things about forms and ngx-sub-form here https://dev.to/maxime1992/building-scalable-robust-and-type-safe-forms-with-angular-3nf9

Body:
I want to implement *ngIf for some div...

Doesn't work:

*ngIf="postForm.value.osnovne.sekcija === vozila"

also

*ngIf="postForm.controls['osnovne'].value.sekcija === vozila

This is my form:

this.postForm = this.fb.group({
      osnovne: this.fb.group({
        sekcija: vozila,
        cena: "",
        dogovor: "",
        opis: ""
      }),
      detaljne: this.fb.group({
        name: "",
        value: ""
      }),
      imagePath: this.fb.group({
        data: ""
      })
    });

How to to that?

Body:
Using ngx-sub-form library it'd be easier to break down your form into sub form components and it'd look like the following:

<form [formGroup]="formGroup">
    <app-osnovne-form [formControlName]="formControlNames.osnovne"></app-osnovne-form>
</form>

<div *ngIf="formGroupValues.osnovne?.sekcija === 'vozila'; else noVozila">
  "vozila" is the current value of osnovne.sekcija
</div>

<ng-template #noVozila>
  "vozila" is not the current value of osnovne.sekcija
</ng-template>

<pre>{{ formGroupValues | json }}</pre>

Here's a live demo: https://stackblitz.com/edit/so-answer-angular-ngif-for-nested-formgroup-value?file=src/app/form/form.component.html

Edit:

If you want to go further, I've just published a blog post to explain a lot of things about forms and ngx-sub-form here https://dev.to/maxime1992/building-scalable-robust-and-type-safe-forms-with-angular-3nf9


问:
Swift Conditional String Interpolation
I often trap myself writing code like this when I need to construct a string depending on some condition (in this case isFavorite):

let me = Contact(name: "Stefan", isFavorite: true)

var message = "Contact \(me.name)"
if me.isFavorite {
    message.append(" is a favorite contact")
}
```

These are 4 lines or alternatively a complex ternary operator (if ? then : else) for such a simple task. I always have a bad conscience with this...

Is there a way to do this more elegantly with Swift?

答:
I tend to create a second String variable which may or may not be empty, and unconditionally append it...

let me = Contact(name: "Stefan", isFavorite: true)
let favorite = me.isFavorite ? " is a favorite contact" : ""

var message = "Contact \(me.name)\(favorite)"
```

Title: Swift Conditional String Interpolation

Body:
I often trap myself writing code like this when I need to construct a string depending on some condition (in this case isFavorite):

let me = Contact(name: "Stefan", isFavorite: true)

var message = "Contact \(me.name)"
if me.isFavorite {
    message.append(" is a favorite contact")
}

These are 4 lines or alternatively a complex ternary operator (if ? then : else) for such a simple task. I always have a bad conscience with this...

Is there a way to do this more elegantly with Swift?


问:
Are these blocks according to PEP8?
are these two samples according to PEP8? Are they ugly? I read a lot of PEP8, but I still feel insecure about multiline blocks...

Personally, I think that one line per param is quite readable when there are many parameters to setup. It is easier to find the parameter and change its value... is it?

tkinter.Label(
    self,
    bg='grey'
    bd=5,
    relief='ridge'
    ).pack(fill='both', exand=1)
```

<pre class="lang-py prettyprint-override"><code>tkinter.Label(
    self,
    bg='grey'
    bd=5,
    relief='ridge').pack(fill='both', exand=1)
</code>```

答:
I think, they are both fine. I'm not aware of an official preference of either of them, as long as you are consistent in your project.

I also don't think there is a need for an official statement as the purpose of line braking is mainly to make the code more readable and every second case would be (from my experience) an exception where the rules don't really fit.

Also fine would be (which I usually en up with):

```<code>tkinter.Label(self,
              bg='grey',
              bd=5,
              relief='ridge').pack(fill='both', exand=1)
</code>```

or

```<code>tkinter.Label(self, bg='grey',
              bd=5, relief='ridge').pack(fill='both', exand=1)
</code>```

but not

```<code>tkinter.Label(self,
    bg='grey',
    bd=5,
    relief='ridge').pack(fill='both', exand=1)
</code>```

Title: Are these blocks according to PEP8?

Body:
are these two samples according to PEP8? Are they ugly? I read a lot of PEP8, but I still feel insecure about multiline blocks...

Personally, I think that one line per param is quite readable when there are many parameters to setup. It is easier to find the parameter and change its value... is it?

tkinter.Label(
    self,
    bg='grey'
    bd=5,
    relief='ridge'
    ).pack(fill='both', exand=1)

tkinter.Label(
    self,
    bg='grey'
    bd=5,
    relief='ridge').pack(fill='both', exand=1)

Body:
I think, they are both fine. I'm not aware of an official preference of either of them, as long as you are consistent in your project.

I also don't think there is a need for an official statement as the purpose of line braking is mainly to make the code more readable and every second case would be (from my experience) an exception where the rules don't really fit.

Also fine would be (which I usually en up with):

tkinter.Label(self,
              bg='grey',
              bd=5,
              relief='ridge').pack(fill='both', exand=1)

or

tkinter.Label(self, bg='grey',
              bd=5, relief='ridge').pack(fill='both', exand=1)

but not

tkinter.Label(self,
    bg='grey',
    bd=5,
    relief='ridge').pack(fill='both', exand=1)


问:
git checkout after a git add?
I wanted to know if there is a way to go back to the previous change in a file on git. If I create a .txt file, I edit it but I don't "git add" can I run "git checkout - file.txt" and go back, but is there a way to do it after doing "git add"?</p>

答:
I wanted to know if there is a way to go back to the previous change in a file on git. If I create a .txt file, I edit it but I don't "git add" can I run "git checkout - file.txt" and go back, but is there a way to do it after doing "git add"?

Provided that the file is in Git, the answer is yes.

It's important here to realize that there are not one but two modifiable copies of some already-committed file, plus many copies that cannot be changed.  The read-only copies are in each of the commits, because every commit you make saves a complete snapshot of every file.1  But it makes this snapshot not from the copy you see and work with.  It makes the snapshot instead from the second modifiable copy, which Git keeps in what Git sometimes calls the index and sometimes calls the staging area.

The names index and staging area refer to the same thing.  It's also sometimes called the cache.  The gitglossary defines cache as "obsolete for index".  One good way to think of the index is that it's the proposed next commit.  When you check out some existing commit, Git fills in both the index and the work-tree from that existing commit.  When you run git add file, Git copies the current version of file into the index, replacing the copy that was in the index.  That is, git add simply updates the proposed new commit.

(If Git made commits directly from the work-tree, you would not need the index at all.  But Git doesn't make commits from the work-tree, and the index takes on an expanded role during a conflicted merge, so you are kind of stuck with learning about the index.)

Normally, you use git checkout branchname to switch to a branch, but you can also write git checkout [--] filename or git checkout branchname [--] filename.2  These are both different from git checkout branchname:

git checkout branchname means switch branches.

git checkout branchname [--] filename means get the given file from the commit at the tip of the named branch.3

git checkout [--] filename means get the given file from the index / staging area.

The way I like to think about this is that as you work on making your new commit, there are three active copies of the file.  One is the frozen one in your current (HEAD or @) commit, one is the modifiable copy in your proposed next commit in the index, and the third is the ordinary file you can see and work with.  Using git checkout -- file.txt gets, into the work-tree where you can work with it, the middle copy—the index copy—which you already overwrote with your earlier git add.  Hence, you want git checkout HEAD -- file.txt: this gets the read-only, committed copy.  It winds up in the index and in your work-tree, at this point, so both of the modifiable copies have been overwritten by this one command.4  Your proposed new commit has the old version of file.txt out of the current commit, and your work-tree has the old version of file.txt out of the current commit.  All three copies—HEAD, index, and work-tree—match again.

1This is true even though git log -p or git show shows you the differences between a commit's parent and the commit.  That's because the way that git log -p or git show finds the differences is that it extracts both the parent commit's copy, and the commit's copy, of the file, and then compares them to see what's different.

Because the committed copies are read-only, every commit that re-uses an old version of the file, doesn't make a new copy, it just refers back to the existing, already-frozen copy.  So the fact that, say, README.md is in a thousand commits, with all the README.md copies exactly the same, really means that there's one copy, shared across the thousand commits.

2The square brackets in [--] indicate that the -- is optional.  It's a good habit to get into using it when you mean the next part is a file name.  Suppose you create a file named master.  Later, you run:

```<code>git checkout master
</code>```

Did you mean: Get me the file named master, or did you mean: *Switch to branch master`?  If you type in:

```<code>git checkout -- master
</code>```

Git knows you meant Get me the file named master.  Whatever comes after -- is assumed to be a file name.  If you type this in without the --, Git thinks you mean switch to branch master.

3You can put in a commit hash ID, or any other name or string that resolves to a commit, here.

4Git being what it is, there's another way to do all of this.  Actually there are many ways, but there is one other main way: you can use git reset [--] filename to copy from HEAD to the index, then git checkout [--] filename to copy from index to work-tree.  But git checkout commit-ish -- filename is shorter and faster.

Title: git checkout after a git add?

Body:
I wanted to know if there is a way to go back to the previous change in a file on git. If I create a .txt file, I edit it but I don't "git add" can I run "git checkout - file.txt" and go back, but is there a way to do it after doing "git add"?

Provided that the file is in Git, the answer is yes.

It's important here to realize that there are not one but two modifiable copies of some already-committed file, plus many copies that cannot be changed.  The read-only copies are in each of the commits, because every commit you make saves a complete snapshot of every file.1  But it makes this snapshot not from the copy you see and work with.  It makes the snapshot instead from the second modifiable copy, which Git keeps in what Git sometimes calls the index and sometimes calls the staging area.

The names index and staging area refer to the same thing.  It's also sometimes called the cache.  The gitglossary defines cache as "obsolete for index".  One good way to think of the index is that it's the proposed next commit.  When you check out some existing commit, Git fills in both the index and the work-tree from that existing commit.  When you run git add file, Git copies the current version of file into the index, replacing the copy that was in the index.  That is, git add simply updates the proposed new commit.

(If Git made commits directly from the work-tree, you would not need the index at all.  But Git doesn't make commits from the work-tree, and the index takes on an expanded role during a conflicted merge, so you are kind of stuck with learning about the index.)

Normally, you use git checkout branchname to switch to a branch, but you can also write git checkout [--] filename or git checkout branchname [--] filename.2  These are both different from git checkout branchname:

git checkout branchname means switch branches.

git checkout branchname [--] filename means get the given file from the commit at the tip of the named branch.3

git checkout [--] filename means get the given file from the index / staging area.

The way I like to think about this is that as you work on making your new commit, there are three active copies of the file.  One is the frozen one in your current (HEAD or @) commit, one is the modifiable copy in your proposed next commit in the index, and the third is the ordinary file you can see and work with.  Using git checkout -- file.txt gets, into the work-tree where you can work with it, the middle copy—the index copy—which you already overwrote with your earlier git add.  Hence, you want git checkout HEAD -- file.txt: this gets the read-only, committed copy.  It winds up in the index and in your work-tree, at this point, so both of the modifiable copies have been overwritten by this one command.4  Your proposed new commit has the old version of file.txt out of the current commit, and your work-tree has the old version of file.txt out of the current commit.  All three copies—HEAD, index, and work-tree—match again.

1This is true even though git log -p or git show shows you the differences between a commit's parent and the commit.  That's because the way that git log -p or git show finds the differences is that it extracts both the parent commit's copy, and the commit's copy, of the file, and then compares them to see what's different.

Because the committed copies are read-only, every commit that re-uses an old version of the file, doesn't make a new copy, it just refers back to the existing, already-frozen copy.  So the fact that, say, README.md is in a thousand commits, with all the README.md copies exactly the same, really means that there's one copy, shared across the thousand commits.

2The square brackets in [--] indicate that the -- is optional.  It's a good habit to get into using it when you mean the next part is a file name.  Suppose you create a file named master.  Later, you run:

git checkout master

Did you mean: Get me the file named master, or did you mean: *Switch to branch master`?  If you type in:

git checkout -- master

Git knows you meant Get me the file named master.  Whatever comes after -- is assumed to be a file name.  If you type this in without the --, Git thinks you mean switch to branch master.

3You can put in a commit hash ID, or any other name or string that resolves to a commit, here.

4Git being what it is, there's another way to do all of this.  Actually there are many ways, but there is one other main way: you can use git reset [--] filename to copy from HEAD to the index, then git checkout [--] filename to copy from index to work-tree.  But git checkout commit-ish -- filename is shorter and faster.


问:
RegEx for replacing a string if it contains more than 2 decimals
I have this user price input that I want to allow 0, 1 or 2 decimal digits.

I'm using comma for decimals.

I'm not using nor allowing thousand separators.

QUESTION:

I want to replace the input if the user enters a third decimal digit.

Somethin like:

5 this is ok

5, this is ok, because it's waiting for the decimals

5,5 this is ok

5,55 this is ok

5,555 this is NOT OK, and I want to delete the last digit and go back to 5,55

5,555555555555 this is also NOT OK, the user might paste something with extra decimal digits and I want to trim them down to 2 decimals maximum, going back again to 5,55

How can I do this?

I know how I can match the end of the string: /[,\d+]$/

But how can I replace with the first two digits after the comma?

答:
You could always temporarily convert the comma to a period, parse the float and fix it to 2 decimals, then replace the period with a comma again like below;

let str = '1,567895'; // price value

let val = parseFloat(str.replace(',', '.')).toFixed(2).replace('.', ',');
console.log(val);```


问:
How to call a function in a component from service directly?
Is there any option to execute method in a component from a service directly?</p>

```<code>@Component({
  selector:'component'
})
export class Component{
  function2(id){
    console.log('ID printed '+ id);
  }
}

@Injectable()

export class Service {
  callfunction2() {
    //how?;
      }
}
</code>```

答:
You shouldn't call a component function from a service.

You could however create a Subject in the service, and subscribe to it from the component.

In that case once callfunction2 is passed, it emits the id value on the Subject, and any components that subscribe to this Subject will receive the value

```<code>@Component({
  selector:'component'
})
export class Component{

  constructor(private service: Service) {}

  function2(id){
    this.service.subject.subscribe(id => {
        console.log('ID printed ' + id);
    });
  }
}

@Injectable()

export class Service {

  public subject: Subject<any> = new Subject<any>();

  callfunction2(id) {
    this.subject.next(id);
  }
}
</code>```

Body:
Is there any option to execute method in a component from a service directly?

@Component({
  selector:'component'
})
export class Component{
  function2(id){
    console.log('ID printed '+ id);
  }
}

@Injectable()

export class Service {
  callfunction2() {
    //how?;
      }
}

Body:
You shouldn't call a component function from a service.

You could however create a Subject in the service, and subscribe to it from the component.

In that case once callfunction2 is passed, it emits the id value on the Subject, and any components that subscribe to this Subject will receive the value

@Component({
  selector:'component'
})
export class Component{

  constructor(private service: Service) {}

  function2(id){
    this.service.subject.subscribe(id => {
        console.log('ID printed ' + id);
    });
  }
}

@Injectable()

export class Service {

  public subject: Subject<any> = new Subject<any>();

  callfunction2(id) {
    this.subject.next(id);
  }
}


问:
When is it "acceptable" to use ViewBag/ViewData in ASP.NET MVC?
I realize that the best practice is to use strongly typed Views and pass in all needed data in a ViewModel, but I am curious if there are situations where it is actually considered "best practice" to pass data in the ViewBag/ViewData.

In what scenarios is the ViewBag/ViewData preferred for passing data to a view?

update

It's great to hear the various uses everyone has come up with for ViewBag/ViewData. We may never arrive at a "best practice" but it will be great to see the different solutions people have come up with that rely on the ViewBag/ViewData.

答:
i can't say about best practice but i mostly use it when using Editor Templates. e.g if i want to display a dropdown list for editing certain field i make following editor template

```<code><%:Html.DropDownList("GetIDHere", new SelectList((IEnumerable<someModel>)ViewData["xyz"]),"select Author")%>
</code>```

Then you put UIHint attribute on BookID field of your model for instance

```<code>public class Book
{
    public int BookID{get;set;}
    [UIHint("mytemplate")]
    public int AuthorID{get;set;}
}
</code>```

in such cases, i assume, its particularly fine and clean to use ViewData. this is the way Telerik asp.net mvc projects have coded in their demo projects demo

Body:
i can't say about best practice but i mostly use it when using Editor Templates. e.g if i want to display a dropdown list for editing certain field i make following editor template

<%:Html.DropDownList("GetIDHere", new SelectList((IEnumerable<someModel>)ViewData["xyz"]),"select Author")%>

Then you put UIHint attribute on BookID field of your model for instance

public class Book
{
    public int BookID{get;set;}
    [UIHint("mytemplate")]
    public int AuthorID{get;set;}
}

in such cases, i assume, its particularly fine and clean to use ViewData. this is the way Telerik asp.net mvc projects have coded in their demo projects demo


问:
How to use a function as a property of an object inside another function in javascript
I'm trying to create a function that will take object as a parameter and inside the object I want to have an object method just same way jQuery ajax works. My problem now is that I can't get that object method to work.

function myAjax({
  type,
  url,
  success
}) {
  var suc = "";
  typeof type === "undefined" ? type = "GET" : type = type;

  var req = new XMLHttpRequest();
  req.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      suc = this.responseText;
      //alert(this.responseText);
    }
  };
  req.open(type, url, false);
  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded ");
  req.send("fname=chijioke&lname=francis");

  function success(suc) {}
  }

  myAjax({
    type: "post",
    url: "page.html",
    success: function(e) {
      alert(e);
    }
  });
```

<p>I want to do something similar to this jQuery ajax call</p>

<pre class="lang-js prettyprint-override"><code>$.ajax({
  type: "post",
  url: "index",
  data: {
    id: id
  },
  success: function(feedback) {
    alert(feedback);
  }
});
</code>```

I need to get the responseText through the success function but it is not working. I want this to work like that of jQuery ajax success, this is really for learning purpose.

答:
What you are trying to do is called a callback function. Rather than declaring a function inside of your function, you should be calling the function being passed to it.

so instead of

```<code>    function success(suc) {}
</code>```

Try doing

```<code>    success(suc);
</code>```

https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced Here's a guide I found on the topic.

Body:
I'm trying to create a function that will take object as a parameter and inside the object I want to have an object method just same way jQuery ajax works. My problem now is that I can't get that object method to work.

function myAjax({
  type,
  url,
  success
}) {
  var suc = "";
  typeof type === "undefined" ? type = "GET" : type = type;

  var req = new XMLHttpRequest();
  req.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      suc = this.responseText;
      //alert(this.responseText);
    }
  };
  req.open(type, url, false);
  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded ");
  req.send("fname=chijioke&lname=francis");

  function success(suc) {}
  }

  myAjax({
    type: "post",
    url: "page.html",
    success: function(e) {
      alert(e);
    }
  });

I want to do something similar to this jQuery ajax call

$.ajax({
  type: "post",
  url: "index",
  data: {
    id: id
  },
  success: function(feedback) {
    alert(feedback);
  }
});

I need to get the responseText through the success function but it is not working. I want this to work like that of jQuery ajax success, this is really for learning purpose.

Body:
What you are trying to do is called a callback function. Rather than declaring a function inside of your function, you should be calling the function being passed to it.

so instead of

    function success(suc) {}

Try doing

    success(suc);

https://codeburst.io/javascript-what-the-heck-is-a-callback-aba4da2deced Here's a guide I found on the topic.


问:
How to add input controls on click of google map marker popup
this code is to show the info text on the pop of click of google marker.

```<code>var infowindow = new google.maps.InfoWindow({
                content: "Add your popup content here"
              });
</code>```

I need to show input controls like text box, dropdown(netsted dropwdown) on this pop up instead of plain info text.

Can somebody provide sample code for this , either in angular js etc.

Help is highly appreceated !!

答:
What you are looking for is called custom html marker.

Basically what you do is create a marker and then programmatically inject html control in there like this:

```<code>function CustomMarker(latlng, map, args) {
    this.latlng = latlng;
    this.args = args;
    this.setMap(map);
}
</code>```

Then set the prototype of the marker:

```<code>CustomMarker.prototype = new google.maps.OverlayView();
</code>```

Then implement the draw function where you can create any html control like div, textbox, drop down etc.:

```<code>CustomMarker.prototype.draw = function() {

    var self = this;

    var div = this.div;

    if (!div) {

        div = this.div = document.createElement('div');

        div.className = 'marker';

        div.style.position = 'absolute';
        div.style.cursor = 'pointer';
        div.style.width = '20px';
        div.style.height = '20px';
        div.style.background = 'blue';

        if (typeof(self.args.marker_id) !== 'undefined') {
            div.dataset.marker_id = self.args.marker_id;
        }

        google.maps.event.addDomListener(div, "click", function(event) {
            google.maps.event.trigger(self, "click");
        });

        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    }

    var point = this.getProjection().fromLatLngToDivPixel(this.latlng);

    if (point) {
        div.style.left = point.x + 'px';
        div.style.top = point.y + 'px';
    }
};
</code>```

You have to still implement the other functions like remove, getPosition etc. as necessary. Details can be found here: https://humaan.com/blog/custom-html-markers-google-maps/

Body:
this code is to show the info text on the pop of click of google marker.

var infowindow = new google.maps.InfoWindow({
                content: "Add your popup content here"
              });

I need to show input controls like text box, dropdown(netsted dropwdown) on this pop up instead of plain info text.

Can somebody provide sample code for this , either in angular js etc.

Help is highly appreceated !!

Body:
What you are looking for is called custom html marker.

Basically what you do is create a marker and then programmatically inject html control in there like this:

function CustomMarker(latlng, map, args) {
    this.latlng = latlng;
    this.args = args;
    this.setMap(map);
}

Then set the prototype of the marker:

CustomMarker.prototype = new google.maps.OverlayView();

Then implement the draw function where you can create any html control like div, textbox, drop down etc.:

CustomMarker.prototype.draw = function() {

    var self = this;

    var div = this.div;

    if (!div) {

        div = this.div = document.createElement('div');

        div.className = 'marker';

        div.style.position = 'absolute';
        div.style.cursor = 'pointer';
        div.style.width = '20px';
        div.style.height = '20px';
        div.style.background = 'blue';

        if (typeof(self.args.marker_id) !== 'undefined') {
            div.dataset.marker_id = self.args.marker_id;
        }

        google.maps.event.addDomListener(div, "click", function(event) {
            google.maps.event.trigger(self, "click");
        });

        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    }

    var point = this.getProjection().fromLatLngToDivPixel(this.latlng);

    if (point) {
        div.style.left = point.x + 'px';
        div.style.top = point.y + 'px';
    }
};

You have to still implement the other functions like remove, getPosition etc. as necessary. Details can be found here: https://humaan.com/blog/custom-html-markers-google-maps/


问:
How can I reduce the size of a 1GB MSI file using Orca?
I have written a C# WPF application. I have now created an MSI that will install the application. However, the file size is gigantic. The application contains many video and image files, which have combined to make the MSI a whopping 1GB in size.

I have tried to reduce the file size with Orca. I have used "Save As" to create a brand new MSI and have also exported the database tables and then imported them to another MSI. In both cases, the file size is reduced to less than 1MB, but then the installer doesn't work at all. Looks like it's not compressing the content, but rather removing it entirely.

How can I use Orca to reduce the MSI file size without stopping the installation from actually working? If there's another way to do it, I'm open to any suggestions.

答:
First, build your installation package with the cabs external (not embedded) in your MSI. That will show you how large the MSI is in relation to the rest of your installation. Chances are you'll find the MSI size is insignificant compared to the content in the cabinet files. My guess is that the video and images are not compressing well in the cabinets.

If my hypothesis is correct, then your goal is to find the optimal compression for the files in the cabinets.

Note: If you use the WiX Toolset to build your MSI, we already do the tricks to ensure the MSI portion is as small as possible. You are not likely to find significant optimizations on top (and if you do, let us know at wix-devs@lists.wixtoolset.org, we'd love to improve :).


问:
Error with Google_sign_in plugin in flutter
I've been trying to fix this for a while now but I can't solve it.
When I use the google_sign_in plugin, I'm able to choose my account but it stops after that.

But after clicking...

Giving me this error(the same) when I click continue:

E/flutter (28971): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null)

Things I've done:

I've searched for hours the error, the ApiException: 10, in Flutter and in Android in general.

Adding a SHA1 key, I've followed multiple tutorials (each one is different one to another, which is really confusing).

Downloaded the new JSON file.

Flutter clean.

Contemplated not using it.

Asking here.

Right now I'm using:

firebase_auth: ^0.11.1

google_sign_in: ^4.0.1+3

The app is in debug mode. I don't have an account to publish in the Google Store.

Thank you in advance.

答:
You must register your fingerprint debug.keystore in firebase,
you probably only registered an release.keystore:

show debug.keystore (linux):

```<code>keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore
</code>```

source: documentation

Body:
You must register your fingerprint debug.keystore in firebase,
you probably only registered an release.keystore:

show debug.keystore (linux):

keytool -list -v -alias androiddebugkey -keystore ~/.android/debug.keystore

source: documentation


问:
Mouse point to viewer coordinates
I have successfully added a cricle into the viewer using the following code:

function addCircle(){

  cameraHUD = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0, 30);
  viewer.impl.createOverlayScene('leaderOverlay-circle',null,null, cameraHUD);

  var circle_geometry = new THREE.CircleGeometry(10, 32);
  var circle_material = new THREE.MeshBasicMaterial({color: 'rgb(1,1,1)'});
  var circle = new THREE.Mesh(circle_geometry, circle_material);
  circle.position.set(100,100,0);

  viewer.impl.addOverlay('leaderOverlay-circle', circle);
  viewer.impl.invalidate(true)

}```
</div>
</div>
</p>

<p>I now  want to add this circle at a point that is clicked in the viewer. My attempts to do this are as follows but the coordiantes are not accurate to the point being clicked on the screen:</p>

<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>function onClick(ev) {

  var wtc = viewer.clientToViewport(ev.clientX - bounds.left, ev.clientY - bounds.top);
  var projectedPoint = new THREE.Vector3(leader.endPoint.x, leader.endPoint.y, leader.endPoint.z);
  projectedPoint.unproject(cameraHUD);
  var circlePosition = viewer.worldToClient(new THREE.Vector3(point.x, point.y, point.z));

  cameraHUD = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0, 30);
  viewer.impl.createOverlayScene('leaderOverlay-circle',null,null, cameraHUD);

  var circle_geometry = new THREE.CircleGeometry(10, 32);
  var circle_material = new THREE.MeshBasicMaterial({color: 'rgb(1,1,1)'});
  var circle = new THREE.Mesh(circle_geometry, circle_material);
  circle.position.set(circlePosition);

  viewer.impl.addOverlay('leaderOverlay-circle', circle);
  viewer.impl.invalidate(true);

}</code>```

答:
Refer to here to project your canvas coordinates to the scene world - see live sample here:</p>

```<code>const camera= this.viewer.navigation.getCamera();
const vec = new THREE.Vector3();
const pos = new THREE.Vector3();

vec.set(
  ( event.clientX / window.innerWidth ) * 2 - 1,
  - ( event.clientY / window.innerHeight ) * 2 + 1,
  0.5 );

vec.unproject( camera );
vec.sub( camera.position ).normalize();
const distance = - camera.position.z / vec.z;
pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );

...
circle.position.set(pos.x,pos.y,pos.z);

</code>```

Title: Mouse point to viewer coordinates

Body:
I have successfully added a cricle into the viewer using the following code:

function addCircle(){

  cameraHUD = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0, 30);
  viewer.impl.createOverlayScene('leaderOverlay-circle',null,null, cameraHUD);

  var circle_geometry = new THREE.CircleGeometry(10, 32);
  var circle_material = new THREE.MeshBasicMaterial({color: 'rgb(1,1,1)'});
  var circle = new THREE.Mesh(circle_geometry, circle_material);
  circle.position.set(100,100,0);

  viewer.impl.addOverlay('leaderOverlay-circle', circle);
  viewer.impl.invalidate(true)

}

I now  want to add this circle at a point that is clicked in the viewer. My attempts to do this are as follows but the coordiantes are not accurate to the point being clicked on the screen:

function onClick(ev) {

  var wtc = viewer.clientToViewport(ev.clientX - bounds.left, ev.clientY - bounds.top);
  var projectedPoint = new THREE.Vector3(leader.endPoint.x, leader.endPoint.y, leader.endPoint.z);
  projectedPoint.unproject(cameraHUD);
  var circlePosition = viewer.worldToClient(new THREE.Vector3(point.x, point.y, point.z));

  cameraHUD = new THREE.OrthographicCamera(-width / 2, width / 2, height / 2, -height / 2, 0, 30);
  viewer.impl.createOverlayScene('leaderOverlay-circle',null,null, cameraHUD);

  var circle_geometry = new THREE.CircleGeometry(10, 32);
  var circle_material = new THREE.MeshBasicMaterial({color: 'rgb(1,1,1)'});
  var circle = new THREE.Mesh(circle_geometry, circle_material);
  circle.position.set(circlePosition);

  viewer.impl.addOverlay('leaderOverlay-circle', circle);
  viewer.impl.invalidate(true);

}

Body:
Refer to here to project your canvas coordinates to the scene world - see live sample here:

const camera= this.viewer.navigation.getCamera();
const vec = new THREE.Vector3();
const pos = new THREE.Vector3();

vec.set(
  ( event.clientX / window.innerWidth ) * 2 - 1,
  - ( event.clientY / window.innerHeight ) * 2 + 1,
  0.5 );

vec.unproject( camera );
vec.sub( camera.position ).normalize();
const distance = - camera.position.z / vec.z;
pos.copy( camera.position ).add( vec.multiplyScalar( distance ) );

...
circle.position.set(pos.x,pos.y,pos.z);


问:
Sending files over Half-duplex interface
I'm trying to send files over a half-duplex interface (RS-485) between a box PC running debian (4.19) and a SBC with an im6xDL.

Thanks to this community I can successfully transfer simple data between the units using picocom or by echoing/reading.

The box PC supports half-duplex RS-485 natively and has automatic RTS functions so that you can read/send data without any issue. The SBC on the other hand needs to be toggled to change into RX or TX mode.

This turned out to be a problem when I tried to send files from the box PC to the SBC.

```<code>On the box PC:
picocom /dev/ttyUSB0 -b 9600 -fn
C-a,C-S
***file: /home/user/test.txt
Transfer incomplete

*** exit status: 128

On the SBC
picocom /dev/ttymxc2 -b 9600 -fn -et
C-a,C-r
Terminal ready
�000000
</code>```

As you can see something is terribly wrong, it is like it cannot interpret the bits when a file is being transferred.

My questions:

Is it possible to send files from the command line in half-duplex systems? (The SBC needs to be in RX mode the entire time).

Is there another way to achieve this that is more intuitive?

As always, thanks for the help and support :)

/W

答:
See here:

Pymodbus - Read input register of Energy meter over rs485 on uart of raspberry pi3

The solution I presented there using pylibmodbus should work for any hardware with UART and one or two GPIO lines accessible from user space in Linux.

If, on the other hand, what you want to do is use something like picocom or minicom then you can take a look at the hardware-only solution using a 555 timer.

Of course, if prototyping circuits is not for you, you can always buy a USB to RS485 with half-duplex support. You have many available but those based on the MAX13487 IC seem to work very well.

EDIT: The solution using the 555 timer is not in the post I linked above but here together with some more background material on half-duplex RS485 links: RS485: Inappropriate ioctl for device

Body:
I'm trying to send files over a half-duplex interface (RS-485) between a box PC running debian (4.19) and a SBC with an im6xDL.

Thanks to this community I can successfully transfer simple data between the units using picocom or by echoing/reading.

The box PC supports half-duplex RS-485 natively and has automatic RTS functions so that you can read/send data without any issue. The SBC on the other hand needs to be toggled to change into RX or TX mode.

This turned out to be a problem when I tried to send files from the box PC to the SBC.

On the box PC:
picocom /dev/ttyUSB0 -b 9600 -fn
C-a,C-S
***file: /home/user/test.txt
Transfer incomplete

*** exit status: 128

On the SBC
picocom /dev/ttymxc2 -b 9600 -fn -et
C-a,C-r
Terminal ready
�000000

As you can see something is terribly wrong, it is like it cannot interpret the bits when a file is being transferred.

My questions:

Is it possible to send files from the command line in half-duplex systems? (The SBC needs to be in RX mode the entire time).

Is there another way to achieve this that is more intuitive?

As always, thanks for the help and support :)

/W


问:
Select multiple files with Intent.ACTION_GET_CONTENT
I'm trying to select multiple files with an Intent, but it seems like I'm missing on something.

I create an Intent.ACTION_GET_CONTENT Intent, put Intent.EXTRA_ALLOW_MULTIPLE as extra in
 (it seems to perfectly fit the purpose) and create a chooser (optional), which chooses the application that should be able to pick multiple files and return them.

The Problem is that I can only pick a single file.

I tried multiple file explorers.
It's API 18 (4.3).

```<code>ACTIVITY_CHOOSE_FILE = 1;  //global constant
Button btn = (Button) this.findViewById(R.id.btnGetFiles);
btn.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    Intent chooseFile;
    Intent intent;
    chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
    chooseFile.setType("file/*");
    chooseFile.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    intent = Intent.createChooser(chooseFile, "Choose a file");
    startActivityForResult(intent, ACTIVITY_CHOOSE_FILE);
  }
});
</code>```

I also added this to the Manifest (it had the same functionality before adding it):

```<code>        <intent-filter>
            <action android:name="android.intent.action.GET_CONTENT" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
</code>```

Why can't I choose multiple files?

(For clarification: the problem is not, that multiple files aren't returned - I can't choose more than 1 file)

答:
Here's the solution in my case it worked for me and allows me to select any kind of file(s).</p>

```<code>// Start intent from your method
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setType("*/*");
startActivityForResult(intent, 1001);

// Get the result from this Overriden method
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case 1001:

                // Checking whether data is null or not
                if (data != null) {

                    // Checking for selection multiple files or single.
                    if (data.getClipData() != null){

                        // Getting the length of data and logging up the logs using index
                        for (int index = 0; index < data.getClipData().getItemCount(); index++) {

                            // Getting the URIs of the selected files and logging them into logcat at debug level
                            Uri uri = data.getClipData().getItemAt(index).getUri();
                            Log.d("filesUri [" + uri + "] : ", String.valueOf(uri) );
                        }
                    }else{

                        // Getting the URI of the selected file and logging into logcat at debug level
                        Uri uri = data.getData();
                        Log.d("fileUri: ", String.valueOf(uri));
                    }
                }
                break;
        }
    }
}
</code>```

Body:
I'm trying to select multiple files with an Intent, but it seems like I'm missing on something.

I create an Intent.ACTION_GET_CONTENT Intent, put Intent.EXTRA_ALLOW_MULTIPLE as extra in
 (it seems to perfectly fit the purpose) and create a chooser (optional), which chooses the application that should be able to pick multiple files and return them.

The Problem is that I can only pick a single file.

I tried multiple file explorers.
It's API 18 (4.3).

ACTIVITY_CHOOSE_FILE = 1;  //global constant
Button btn = (Button) this.findViewById(R.id.btnGetFiles);
btn.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick(View v) {
    Intent chooseFile;
    Intent intent;
    chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
    chooseFile.setType("file/*");
    chooseFile.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    intent = Intent.createChooser(chooseFile, "Choose a file");
    startActivityForResult(intent, ACTIVITY_CHOOSE_FILE);
  }
});

I also added this to the Manifest (it had the same functionality before adding it):

        <intent-filter>
            <action android:name="android.intent.action.GET_CONTENT" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>

Why can't I choose multiple files?

(For clarification: the problem is not, that multiple files aren't returned - I can't choose more than 1 file)

Body:
Here's the solution in my case it worked for me and allows me to select any kind of file(s).

// Start intent from your method
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
intent.setType("*/*");
startActivityForResult(intent, 1001);

// Get the result from this Overriden method
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (resultCode == RESULT_OK) {
        switch (requestCode) {
            case 1001:

                // Checking whether data is null or not
                if (data != null) {

                    // Checking for selection multiple files or single.
                    if (data.getClipData() != null){

                        // Getting the length of data and logging up the logs using index
                        for (int index = 0; index < data.getClipData().getItemCount(); index++) {

                            // Getting the URIs of the selected files and logging them into logcat at debug level
                            Uri uri = data.getClipData().getItemAt(index).getUri();
                            Log.d("filesUri [" + uri + "] : ", String.valueOf(uri) );
                        }
                    }else{

                        // Getting the URI of the selected file and logging into logcat at debug level
                        Uri uri = data.getData();
                        Log.d("fileUri: ", String.valueOf(uri));
                    }
                }
                break;
        }
    }
}


问:
Kafka Consumer: No entry found for connection
I am trying to check the kafka consumer by consuming the data from a topic on a remote Kafka cluster. I am getting the following error when I use the kafka-console-consumer.sh:

```<code> ERROR Error processing message, terminating consumer process:  (kafka.tools.ConsoleConsumer$)
java.lang.IllegalStateException: No entry found for connection 2147475658
    at org.apache.kafka.clients.ClusterConnectionStates.nodeState(ClusterConnectionStates.java:330)
    at org.apache.kafka.clients.ClusterConnectionStates.disconnected(ClusterConnectionStates.java:134)
    at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:885)
    at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:276)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.tryConnect(ConsumerNetworkClient.java:548)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator$FindCoordinatorResponseHandler.onSuccess(AbstractCoordinator.java:655)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator$FindCoordinatorResponseHandler.onSuccess(AbstractCoordinator.java:635)
    at org.apache.kafka.clients.consumer.internals.RequestFuture$1.onSuccess(RequestFuture.java:204)
    at org.apache.kafka.clients.consumer.internals.RequestFuture.fireSuccess(RequestFuture.java:167)
    at org.apache.kafka.clients.consumer.internals.RequestFuture.complete(RequestFuture.java:127)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient$RequestFutureCompletionHandler.fireCompletion(ConsumerNetworkClient.java:575)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.firePendingCompletedRequests(ConsumerNetworkClient.java:389)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:297)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:236)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:215)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureCoordinatorReady(AbstractCoordinator.java:231)
    at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.poll(ConsumerCoordinator.java:316)
    at org.apache.kafka.clients.consumer.KafkaConsumer.updateAssignmentMetadataIfNeeded(KafkaConsumer.java:1214)
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1179)
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1164)
    at kafka.tools.ConsoleConsumer$ConsumerWrapper.receive(ConsoleConsumer.scala:436)
    at kafka.tools.ConsoleConsumer$.process(ConsoleConsumer.scala:104)
    at kafka.tools.ConsoleConsumer$.run(ConsoleConsumer.scala:76)
    at kafka.tools.ConsoleConsumer$.main(ConsoleConsumer.scala:54)
    at kafka.tools.ConsoleConsumer.main(ConsoleConsumer.scala)
Processed a total of 0 messages
</code>```

Here is the command that I use:

```<code>./bin/kafka-console-consumer.sh --bootstrap-server SSL://{IP}:{PORT},SSL://{IP}:{PORT},SSL://{IP}:{PORT} --consumer.config ./config/consumer.properties --topic MYTOPIC --group MYGROUP
</code>```

Here is the ./config/consumer.properties file:

```<code>bootstrap.servers=SSL://{IP}:{PORT},SSL://{IP}:{PORT},SSL://{IP}:{PORT}

# consumer group id
group.id=MYGROUP

# What to do when there is no initial offset in Kafka or if the current
# offset does not exist any more on the server: latest, earliest, none
auto.offset.reset=earliest

#### Security
security.protocol=SSL
ssl.key.password=test1234
ssl.keystore.location=/opt/kafka/config/certs/keystore.jks
ssl.keystore.password=test1234
ssl.truststore.location=/opt/kafka/config/certs/truststore.jks
ssl.truststore.password=test1234
</code>```

Do you have any idea what the problem is?

答:
In my case I was receiving that while trying to connect to my Kafka container, I had to pass the following:

-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092

-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092

Hope it helps someone

Body:
I am trying to check the kafka consumer by consuming the data from a topic on a remote Kafka cluster. I am getting the following error when I use the kafka-console-consumer.sh:

 ERROR Error processing message, terminating consumer process:  (kafka.tools.ConsoleConsumer$)
java.lang.IllegalStateException: No entry found for connection 2147475658
    at org.apache.kafka.clients.ClusterConnectionStates.nodeState(ClusterConnectionStates.java:330)
    at org.apache.kafka.clients.ClusterConnectionStates.disconnected(ClusterConnectionStates.java:134)
    at org.apache.kafka.clients.NetworkClient.initiateConnect(NetworkClient.java:885)
    at org.apache.kafka.clients.NetworkClient.ready(NetworkClient.java:276)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.tryConnect(ConsumerNetworkClient.java:548)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator$FindCoordinatorResponseHandler.onSuccess(AbstractCoordinator.java:655)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator$FindCoordinatorResponseHandler.onSuccess(AbstractCoordinator.java:635)
    at org.apache.kafka.clients.consumer.internals.RequestFuture$1.onSuccess(RequestFuture.java:204)
    at org.apache.kafka.clients.consumer.internals.RequestFuture.fireSuccess(RequestFuture.java:167)
    at org.apache.kafka.clients.consumer.internals.RequestFuture.complete(RequestFuture.java:127)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient$RequestFutureCompletionHandler.fireCompletion(ConsumerNetworkClient.java:575)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.firePendingCompletedRequests(ConsumerNetworkClient.java:389)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:297)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:236)
    at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:215)
    at org.apache.kafka.clients.consumer.internals.AbstractCoordinator.ensureCoordinatorReady(AbstractCoordinator.java:231)
    at org.apache.kafka.clients.consumer.internals.ConsumerCoordinator.poll(ConsumerCoordinator.java:316)
    at org.apache.kafka.clients.consumer.KafkaConsumer.updateAssignmentMetadataIfNeeded(KafkaConsumer.java:1214)
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1179)
    at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1164)
    at kafka.tools.ConsoleConsumer$ConsumerWrapper.receive(ConsoleConsumer.scala:436)
    at kafka.tools.ConsoleConsumer$.process(ConsoleConsumer.scala:104)
    at kafka.tools.ConsoleConsumer$.run(ConsoleConsumer.scala:76)
    at kafka.tools.ConsoleConsumer$.main(ConsoleConsumer.scala:54)
    at kafka.tools.ConsoleConsumer.main(ConsoleConsumer.scala)
Processed a total of 0 messages

Here is the command that I use:

./bin/kafka-console-consumer.sh --bootstrap-server SSL://{IP}:{PORT},SSL://{IP}:{PORT},SSL://{IP}:{PORT} --consumer.config ./config/consumer.properties --topic MYTOPIC --group MYGROUP

Here is the ./config/consumer.properties file:

bootstrap.servers=SSL://{IP}:{PORT},SSL://{IP}:{PORT},SSL://{IP}:{PORT}

# consumer group id
group.id=MYGROUP

# What to do when there is no initial offset in Kafka or if the current
# offset does not exist any more on the server: latest, earliest, none
auto.offset.reset=earliest

#### Security
security.protocol=SSL
ssl.key.password=test1234
ssl.keystore.location=/opt/kafka/config/certs/keystore.jks
ssl.keystore.password=test1234
ssl.truststore.location=/opt/kafka/config/certs/truststore.jks
ssl.truststore.password=test1234

Do you have any idea what the problem is?