问:
Firebase Instrument test time out
I ran the instrumentation test locally and everything is fine.
But It is always failed which times out when I connect to Firebase Test Lab. I have tried a few different devices but still no luck. Most of them just stuck in there and fail for a half hour.

```<code>android.support.test.espresso.PerformException: Error performing 'single click - At Coordinates: 539, 665 and precision: 16, 16' on view 'with id: package.name.dev:id/emailSignButton'.

at android.support.test.espresso.PerformException$Builder.build(PerformException.java:83)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:80)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:56)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:184)
at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115)
at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87)
at package.name.Utils$Companion.login(Utils.kt:42)
at package.name.views.active.SomeActivityTest.testPrebidAuction(SomeActivityTest.java:62)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class fragment
Caused by: android.support.v8.renderscript.RSRuntimeException: Error loading RS jni library: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/package.name.dev.test-Fa1GKc9fQmFQRxv4qGFwHg==/lib/arm64/librsjni.so" is 64-bit instead of 32-bit Support lib API: 2301
at android.support.v8.renderscript.RenderScript.internalCreate(RenderScript.java:1414)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1599)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1549)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1525)
at at.favre.lib.dali.builder.ContextWrapper.getRenderScript(ContextWrapper.java:36)
at at.favre.lib.dali.builder.blur.BlurBuilder.<init>(BlurBuilder.java:72)
at at.favre.lib.dali.Dali.load(Dali.java:123)
at package.name.ui.BackgroundImageFragment.onCreateView(BackgroundImageFragment.kt:44)
</code>```

答:
How long do your tests take to run?  You may need to set a longer test timeout than the default timeout value in FTL, particularly if you use any virtual devices, which do not have a GPU to speed up graphic operations.

You can set the test timeout using advanced options from the Firebase Console, or by using the --timeout flag if you're using gcloud from the command line.

Title: Firebase Instrument test time out

Body:
I ran the instrumentation test locally and everything is fine.
But It is always failed which times out when I connect to Firebase Test Lab. I have tried a few different devices but still no luck. Most of them just stuck in there and fail for a half hour.

android.support.test.espresso.PerformException: Error performing 'single click - At Coordinates: 539, 665 and precision: 16, 16' on view 'with id: package.name.dev:id/emailSignButton'.

at android.support.test.espresso.PerformException$Builder.build(PerformException.java:83)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:80)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:56)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:184)
at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115)
at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87)
at package.name.Utils$Companion.login(Utils.kt:42)
at package.name.views.active.SomeActivityTest.testPrebidAuction(SomeActivityTest.java:62)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
Caused by: android.view.InflateException: Binary XML file line #10: Binary XML file line #10: Error inflating class fragment
Caused by: android.view.InflateException: Binary XML file line #10: Error inflating class fragment
Caused by: android.support.v8.renderscript.RSRuntimeException: Error loading RS jni library: java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/package.name.dev.test-Fa1GKc9fQmFQRxv4qGFwHg==/lib/arm64/librsjni.so" is 64-bit instead of 32-bit Support lib API: 2301
at android.support.v8.renderscript.RenderScript.internalCreate(RenderScript.java:1414)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1599)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1549)
at android.support.v8.renderscript.RenderScript.create(RenderScript.java:1525)
at at.favre.lib.dali.builder.ContextWrapper.getRenderScript(ContextWrapper.java:36)
at at.favre.lib.dali.builder.blur.BlurBuilder.<init>(BlurBuilder.java:72)
at at.favre.lib.dali.Dali.load(Dali.java:123)
at package.name.ui.BackgroundImageFragment.onCreateView(BackgroundImageFragment.kt:44)


来源: stackexchange

问:
Best way to search data in xml files?
In our new project we have to provide a search functionality to retrieve data from hundreds of xml files. I have a brief of our current plan below, I would like to know your suggestions/improvements on this.

These xml files contain personal information, and the search is based on 10 elements in it for example last name, first name, email etc. Our current plan is to create an master XmlDocument with all the searchable data and a key to the actual file. So that when the user searches the data we first look at master file and get the the results. We will also cache the actual xml files from the recent searches so simillar searches later can be handled quickly.

Our application is a .net 2.0 web application.

答:
Hmm, sounds like your building a database over the top of Xml, for performance I'd be reading those files into the DB of your choice, and let it handle indexing and searching for you. If that's not an option get really with XPath, or roll your own exhaustive search using XmlReader.

Xml is not the answer to every problem, however clean it appears to be, performance will suck.

OwnerDisplayName: gk

ContentLicense: CC BY-SA 2.5

Title: Best way to search data in xml files?

OwnerDisplayName: MrTelly


问:
Stubbing out method with ArrayList/List param fails when using any() or anyList()
I have a java class.

```<code>class Blah{
        public Blah(){

        }
        public String testMe(List<String> s){
            return new String("hello "+s.get(0));
        }

        public String testMeString(String s){
            return new String("hello "+s);
        }

    }
</code>```

I am unable trying to stub and test the testMe method successfully. Note that I am just trying to understand mocking in java. For example I have tried:

```<code>    @Test
    public void testTestMe(){
        Blah blah = spy(new Blah());
        ArrayList<String> l = new ArrayList<String>();
        l.add("oopsie");
        when(blah.testMe(Matchers.any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMe(l));
</code>```

This returns a NullPointerException. I have also tried any(List.class), any(ArrayList.class). I have also tried using anyList() but this gives me an IndexOutOfBounds error. What am I doing wrong?
Interestingly, my testMeString works fine. If I do

```<code>@Test
    public void testTestMeString(){
        Blah blah = spy(new Blah());
        when(blah.testMeString(any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMeString("lala"));
}
</code>```

the tests pass with any() and any(String.class).

答:
You should reconsider using spy, mock etc. those facilities should be used when you have an external system, rest web service, DB you don't want to call during unit tests. In simple scenarios like this one just create some test input and check the output.

```<code>@Test public void testTestMeString(){
 //given
  List<String> list = Arrays.asList("aaa");
 //when
 String result = blah.testMe(list);
 //then
 assertEquals(result, "hello aaa");
 }
</code>```

When you are interested in given, when, then check BDD.

ContentLicense: CC BY-SA 4.0

Body:
I have a java class.

class Blah{
        public Blah(){

        }
        public String testMe(List<String> s){
            return new String("hello "+s.get(0));
        }

        public String testMeString(String s){
            return new String("hello "+s);
        }

    }

I am unable trying to stub and test the testMe method successfully. Note that I am just trying to understand mocking in java. For example I have tried:

    @Test
    public void testTestMe(){
        Blah blah = spy(new Blah());
        ArrayList<String> l = new ArrayList<String>();
        l.add("oopsie");
        when(blah.testMe(Matchers.any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMe(l));

This returns a NullPointerException. I have also tried any(List.class), any(ArrayList.class). I have also tried using anyList() but this gives me an IndexOutOfBounds error. What am I doing wrong?
Interestingly, my testMeString works fine. If I do

@Test
    public void testTestMeString(){
        Blah blah = spy(new Blah());
        when(blah.testMeString(any())).thenReturn("intercepted");
        assertEquals("intercepted",blah.testMeString("lala"));
}

the tests pass with any() and any(String.class).

Body:
You should reconsider using spy, mock etc. those facilities should be used when you have an external system, rest web service, DB you don't want to call during unit tests. In simple scenarios like this one just create some test input and check the output.

@Test public void testTestMeString(){
 //given
  List<String> list = Arrays.asList("aaa");
 //when
 String result = blah.testMe(list);
 //then
 assertEquals(result, "hello aaa");
 }

When you are interested in given, when, then check BDD.


问:
PHP Remove duplicates from multidimensional array based on key
I have a multidimensional array ($array) in which the entries look like:

```<code>{ ["upload/example.gif"]=> array(5) {
     ["title"]=> string(12) "This is me"
     ["excerpt"]=> string(24) "This is a photo of a tree"
     ["img"]=> string(42) "upload/example.gif"
     ["link"]=> string(23) "http://www.google.co.uk"
     ["source"]=> string(6) "custom"
   }
}
</code>```

I need to be able to remove any duplicate values in $array based on the key. So if my array was:

```<code>$array = array( ["upload/example.gif"] => etc....
                ["upload/tree.gif"] => etc....
                ["upload/example.gif"] => etc....)
</code>```

I would be able to remove one of the ["upload/example.gif"] => etc.... arrays.

I have tried:

```<code>$array = array_map('unserialize', array_unique(array_map('serialize', $array)));
</code>```

but that didn't work.

Thanks in advance.

答:
netcoder answered the question properly, I just wanted it to show up in the answer box (instead of comment).

You can't have duplicate keys in an associative array (or any array).  By nature of it being an array you can be gauranteed to have unique keys.

BTW if you find duplicate data in different keys you can remove the redundant key by unsetting it.

```<code>unset($array['delete_me']);
</code>```

http://php.net/manual/en/function.unset.php

ContentLicense: CC BY-SA 3.0

Body:
I have a multidimensional array ($array) in which the entries look like:

{ ["upload/example.gif"]=> array(5) {
     ["title"]=> string(12) "This is me"
     ["excerpt"]=> string(24) "This is a photo of a tree"
     ["img"]=> string(42) "upload/example.gif"
     ["link"]=> string(23) "http://www.google.co.uk"
     ["source"]=> string(6) "custom"
   }
}

I need to be able to remove any duplicate values in $array based on the key. So if my array was:

$array = array( ["upload/example.gif"] => etc....
                ["upload/tree.gif"] => etc....
                ["upload/example.gif"] => etc....)

I would be able to remove one of the ["upload/example.gif"] => etc.... arrays.

I have tried:

$array = array_map('unserialize', array_unique(array_map('serialize', $array)));

but that didn't work.

Thanks in advance.

Body:
netcoder answered the question properly, I just wanted it to show up in the answer box (instead of comment).

You can't have duplicate keys in an associative array (or any array).  By nature of it being an array you can be gauranteed to have unique keys.

BTW if you find duplicate data in different keys you can remove the redundant key by unsetting it.

unset($array['delete_me']);

http://php.net/manual/en/function.unset.php


问:
How to count multiple variables with strlen
I am looking to count the length of strings in multiple variables and add them together to get the total count.

I have tried strlen but have either messed up the syntax or have not used the proper code.

```<code>//$_SESSION['var1'] and $_SESSION['var2'] will each be numbers from -30.0 to 1000.0. I need the lengths of the two variables to be added. I need the negative sign(s) and decimal separators, or dots, to be counted.

$_SESSION['var_array'] = $_SESSION['var1'].$_SESSION['var2'];
$_SESSION['var_count'] = strlen($_SESSION['var_array']);
</code>```

or

```<code>$_SESSION['var_count'] = strlen($_SESSION['var1'])+strlen($_SESSION['var2']);
</code>```

Various results are observed. Sometimes the correct number IS observed but usually not.

答:
The problem is that just storing numeric values doesn't maintain trailing decimals if they are 0.  You could alternatively store them as strings, which will maintain the values exactly as you want them or format the numbers to ensure they contain the right format.  The following code shows what I mean...</p>

```<code>$_SESSION['var1'] = -30.0;
echo $_SESSION['var1'].PHP_EOL; // Gives -30

$_SESSION['var1'] = number_format($_SESSION['var1'], 1);
echo $_SESSION['var1'].PHP_EOL;  // gives -30.0

$_SESSION['var2'] = "1000.0";
echo $_SESSION['var1'].PHP_EOL;  // gives 1000.0

$_SESSION['var_array'] = $_SESSION['var1'].$_SESSION['var2'];
echo strlen($_SESSION['var_array']);  // gives 11
</code>```

Body:
I am looking to count the length of strings in multiple variables and add them together to get the total count.

I have tried strlen but have either messed up the syntax or have not used the proper code.

//$_SESSION['var1'] and $_SESSION['var2'] will each be numbers from -30.0 to 1000.0. I need the lengths of the two variables to be added. I need the negative sign(s) and decimal separators, or dots, to be counted.

$_SESSION['var_array'] = $_SESSION['var1'].$_SESSION['var2'];
$_SESSION['var_count'] = strlen($_SESSION['var_array']);

or

$_SESSION['var_count'] = strlen($_SESSION['var1'])+strlen($_SESSION['var2']);

Various results are observed. Sometimes the correct number IS observed but usually not.

Body:
The problem is that just storing numeric values doesn't maintain trailing decimals if they are 0.  You could alternatively store them as strings, which will maintain the values exactly as you want them or format the numbers to ensure they contain the right format.  The following code shows what I mean...

$_SESSION['var1'] = -30.0;
echo $_SESSION['var1'].PHP_EOL; // Gives -30

$_SESSION['var1'] = number_format($_SESSION['var1'], 1);
echo $_SESSION['var1'].PHP_EOL;  // gives -30.0

$_SESSION['var2'] = "1000.0";
echo $_SESSION['var1'].PHP_EOL;  // gives 1000.0

$_SESSION['var_array'] = $_SESSION['var1'].$_SESSION['var2'];
echo strlen($_SESSION['var_array']);  // gives 11


问:
Trim the string data fetched from the table in delphi using ado dataset
I have got a table column of datatype char and by making use of ADO dataset I am fetching the data. But because of type char, it displays the data with trailing extra spaces. And the form on which this ADO dataset lies is inherited by many forms. I want to trim the extra spaces by making  some change in the Delphi code on parent form by using some ADO dataset property

I have made use of FixedChar property of the data field by making it to false but that did not work

答:
You can also set the OnGetText event of the field and trim the text:</p>

```<code>procedure TMyForm.AdoDataSet1GetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  Text := Trim(Text);
end;
</code>```

Body:
You can also set the OnGetText event of the field and trim the text:

procedure TMyForm.AdoDataSet1GetText(Sender: TField; var Text: string; DisplayText: Boolean);
begin
  Text := Trim(Text);
end;


问:
Combine rows help. Rows are the exact same
All of my queries produce data at the item level. When I want to run reports across several months, I often run out of rows in excel due to this problem.

IF a customer orders 5 shirts, and they are shipped in the same package, my query produces 5 rows of the exact same data. I don't care what the customer ordered, I just want to know that 1 package went out. Possibly containing 5 units (Qty in the query).

I tried using the "max" function but the query failed.

```<code>select

p.TrackingNumber,
oh.BusinessUnitCode,
cc.Qty,
oh.ShipCode,
p.ContainerID,
convert(date,oh.ShipTime) as 'OrderDate',
oh.OrderNumber

from dmhost.tblOrderHeader oh

join dmhost.tblContainer c on oh.OrderHeaderID = c.OrderHeaderID
join dmhost.tblPackage p on c.ContainerID = p.ContainerID
join dmhost.tblContainerContents cc on c.ContainerID = cc.ContainerID
join dmhost.tblItemMaster im on im.ItemMasterID = cc.ItemMasterID

where (oh.ShipTime between '2018-05-01' and '2018-05-16')

and cc.Qty <> 0

order by p.ContainerID
</code>```

The results produces several rows with all of the EXACT same information. The reason for this, is because the customer ordered several items, and they were all shipped in the same package. I only want one line of data for each package.

答:
This is a job for GROUP BY. You haven't provided enough information to tell us exactly what you want in each result row. So this is a guess:

```<code>SELECT oh.BusinessUnitCode,
       SUM(cc.Qty) Qty,
       COUNT(*) OrderCount,
       oh.ShipCode,
       p.ContainerID,
       convert(date,oh.ShipTime) as 'OrderDate'
  FROM whatever tables and joins
 WHERE whatever filters
 GROUP BY oh.BusinessUnitCode,
       oh.ShipCode,
       p.ContainerID,
       convert(date,oh.ShipTime)
</code>```

This summarizes your detail rows.

Body:
All of my queries produce data at the item level. When I want to run reports across several months, I often run out of rows in excel due to this problem.

IF a customer orders 5 shirts, and they are shipped in the same package, my query produces 5 rows of the exact same data. I don't care what the customer ordered, I just want to know that 1 package went out. Possibly containing 5 units (Qty in the query).

I tried using the "max" function but the query failed.

select

p.TrackingNumber,
oh.BusinessUnitCode,
cc.Qty,
oh.ShipCode,
p.ContainerID,
convert(date,oh.ShipTime) as 'OrderDate',
oh.OrderNumber

from dmhost.tblOrderHeader oh

join dmhost.tblContainer c on oh.OrderHeaderID = c.OrderHeaderID
join dmhost.tblPackage p on c.ContainerID = p.ContainerID
join dmhost.tblContainerContents cc on c.ContainerID = cc.ContainerID
join dmhost.tblItemMaster im on im.ItemMasterID = cc.ItemMasterID

where (oh.ShipTime between '2018-05-01' and '2018-05-16')

and cc.Qty <> 0

order by p.ContainerID

The results produces several rows with all of the EXACT same information. The reason for this, is because the customer ordered several items, and they were all shipped in the same package. I only want one line of data for each package.

Body:
This is a job for GROUP BY. You haven't provided enough information to tell us exactly what you want in each result row. So this is a guess:

SELECT oh.BusinessUnitCode,
       SUM(cc.Qty) Qty,
       COUNT(*) OrderCount,
       oh.ShipCode,
       p.ContainerID,
       convert(date,oh.ShipTime) as 'OrderDate'
  FROM whatever tables and joins
 WHERE whatever filters
 GROUP BY oh.BusinessUnitCode,
       oh.ShipCode,
       p.ContainerID,
       convert(date,oh.ShipTime)

This summarizes your detail rows.


问:
conditional if/else statements across two data frames in R
I have a data.frame of a few columns of known/expected results and want to compare these to a second data.frame with the same structure but potentially different results. There are four possible scenarios:

TruePositive (TP) == elements of the known/observed vectors contain the same information and neither are NA

TrueNegative (TN) == elements of the known/observed vectors are both NA

FalsePositive (FP) == known is NA, while observed is some nonNA value

FalseNegative (FN) == known is some nonNA value, observed is NA

I'd like to to produce a new data.frame that evaluates those four conditions for each of the columns among the known/observed data.frames

I have come across posts that describe multiple conditions within a vector, but I haven't seen any information on comparing the elements of two vectors that share the same index (in R).

Let's say for simplicity you have a pair of maps: the "True" map is what we expect, and the "observed" map is what we have recorded. For both maps, these observations occur at identical locations, and each location is broken up into three parts (Country, Region, and Zone).

```<code>true_map <- data.frame(
  MapSection = paste0("mapsection", seq(1:5)),
  Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
  Region = c(rep("Ontario", 3), "NewYork", "Alaska"),
  Zone = c("Toronto", "Ottawa", NA, "Albany", NA)
)

obsrvd_map <- data.frame(
  MapSection = paste0("mapsection", seq(1:5)),
  Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
  Region = c(rep("Ontario", 2), NA, "NewYork", "Alaska"),
  Zone = c("Toronto", "Ottawa", NA, "Albany", "Fairbanks")
)
</code>```

At the Country level, the true and observed maps are identical. At the Region level however, mapsection3 is missing information in the "observed" map (NA), while the "true" map has a location (Ontario). This would be classified as a FalseNegative, because we are missing information where we expect it to be.
Conversely, mapsection5 is missing information in the "true" map at the Zone level, while the "observed" map contains information (Fairbanks). This would be classified as a FalsePositive because there is additional information where we do not expect information. However, both the "true" and "observed" maps are lacking information in the Zone level for mapsection3. This would be considered a TrueNegative because both are missing information.

The final result would summarize these observations as follows:

```<code>MapSection Country Region Zone
mapsection1      TP     TP   TP
mapsection2      TP     TP   TP
mapsection3      TP     FN   TN
mapsection4      TP     TP   TP
mapsection5      TP     TP   FP
</code>```

Thank you for your assistance!

答:
The logic in your answer looks solid, it just doesn't yet scale to the other combinations you need. To do that, I'd reshape the data into a long form so you have one column of geographic levels and one of zones.

library(dplyr)
library(tidyr)

true_map_long <- true_map %>%
  gather(key = level, value = value, -MapSection)
obsrvd_map_long <- obsrvd_map %>%
  gather(key = level, value = value, -MapSection)
```

<p>Both are shaped like:</p>

<pre class="lang-r prettyprint-override"><code>head(true_map_long)
#>    MapSection   level        value
#> 1 mapsection1 Country       Canada
#> 2 mapsection2 Country       Canada
#> 3 mapsection3 Country       Canada
#> 4 mapsection4 Country UnitedStates
#> 5 mapsection5 Country UnitedStates
#> 6 mapsection1  Region      Ontario
</code>```

Join these two long-shaped tables by map section and level, and give appropriate suffixes to make it clearer which is which. The case_when is essentially the same, but now you're not tied to one location.

joined <- inner_join(
  true_map_long,
  obsrvd_map_long,
  by = c("MapSection", "level"),
  suffix = c("_t", "_o")
) %>%
  mutate(truth = case_when(
    value_t == value_o  ~ "TP",
    is.na(value_t) == is.na(value_o)  ~ "TN",
    is.na(value_t) & !is.na(value_o)  ~ "FP",
    !is.na(value_t) & is.na(value_o)  ~ "FN",
  ))
head(joined)
#>    MapSection   level      value_t      value_o truth
#> 1 mapsection1 Country       Canada       Canada    TP
#> 2 mapsection2 Country       Canada       Canada    TP
#> 3 mapsection3 Country       Canada       Canada    TP
#> 4 mapsection4 Country UnitedStates UnitedStates    TP
#> 5 mapsection5 Country UnitedStates UnitedStates    TP
#> 6 mapsection1  Region      Ontario      Ontario    TP
```

<p>Then drop the value columns and spread to a wide shape again. You could do this and the joining in one step; breaking into two parts was just easier for explaining.</p>

<pre class="lang-r prettyprint-override"><code>joined %>%
  select(-starts_with("value")) %>%
  spread(key = level, value = truth)
#>    MapSection Country Region Zone
#> 1 mapsection1      TP     TP   TP
#> 2 mapsection2      TP     TP   TP
#> 3 mapsection3      TP     FN   TN
#> 4 mapsection4      TP     TP   TP
#> 5 mapsection5      TP     TP   FP
</code>```

Created on 2019-05-31 by the reprex package (v0.3.0)

Body:
I have a data.frame of a few columns of known/expected results and want to compare these to a second data.frame with the same structure but potentially different results. There are four possible scenarios:

TruePositive (TP) == elements of the known/observed vectors contain the same information and neither are NA

TrueNegative (TN) == elements of the known/observed vectors are both NA

FalsePositive (FP) == known is NA, while observed is some nonNA value

FalseNegative (FN) == known is some nonNA value, observed is NA

I'd like to to produce a new data.frame that evaluates those four conditions for each of the columns among the known/observed data.frames

I have come across posts that describe multiple conditions within a vector, but I haven't seen any information on comparing the elements of two vectors that share the same index (in R).

Let's say for simplicity you have a pair of maps: the "True" map is what we expect, and the "observed" map is what we have recorded. For both maps, these observations occur at identical locations, and each location is broken up into three parts (Country, Region, and Zone).

true_map <- data.frame(
  MapSection = paste0("mapsection", seq(1:5)),
  Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
  Region = c(rep("Ontario", 3), "NewYork", "Alaska"),
  Zone = c("Toronto", "Ottawa", NA, "Albany", NA)
)

obsrvd_map <- data.frame(
  MapSection = paste0("mapsection", seq(1:5)),
  Country = c(rep("Canada", 3), rep("UnitedStates", 2)),
  Region = c(rep("Ontario", 2), NA, "NewYork", "Alaska"),
  Zone = c("Toronto", "Ottawa", NA, "Albany", "Fairbanks")
)

At the Country level, the true and observed maps are identical. At the Region level however, mapsection3 is missing information in the "observed" map (NA), while the "true" map has a location (Ontario). This would be classified as a FalseNegative, because we are missing information where we expect it to be.
Conversely, mapsection5 is missing information in the "true" map at the Zone level, while the "observed" map contains information (Fairbanks). This would be classified as a FalsePositive because there is additional information where we do not expect information. However, both the "true" and "observed" maps are lacking information in the Zone level for mapsection3. This would be considered a TrueNegative because both are missing information.

The final result would summarize these observations as follows:

MapSection Country Region Zone
mapsection1      TP     TP   TP
mapsection2      TP     TP   TP
mapsection3      TP     FN   TN
mapsection4      TP     TP   TP
mapsection5      TP     TP   FP

Thank you for your assistance!

Body:
The logic in your answer looks solid, it just doesn't yet scale to the other combinations you need. To do that, I'd reshape the data into a long form so you have one column of geographic levels and one of zones.

library(dplyr)
library(tidyr)

true_map_long <- true_map %>%
  gather(key = level, value = value, -MapSection)
obsrvd_map_long <- obsrvd_map %>%
  gather(key = level, value = value, -MapSection)

Both are shaped like:

head(true_map_long)
#>    MapSection   level        value
#> 1 mapsection1 Country       Canada
#> 2 mapsection2 Country       Canada
#> 3 mapsection3 Country       Canada
#> 4 mapsection4 Country UnitedStates
#> 5 mapsection5 Country UnitedStates
#> 6 mapsection1  Region      Ontario

Join these two long-shaped tables by map section and level, and give appropriate suffixes to make it clearer which is which. The case_when is essentially the same, but now you're not tied to one location.

joined <- inner_join(
  true_map_long,
  obsrvd_map_long,
  by = c("MapSection", "level"),
  suffix = c("_t", "_o")
) %>%
  mutate(truth = case_when(
    value_t == value_o  ~ "TP",
    is.na(value_t) == is.na(value_o)  ~ "TN",
    is.na(value_t) & !is.na(value_o)  ~ "FP",
    !is.na(value_t) & is.na(value_o)  ~ "FN",
  ))
head(joined)
#>    MapSection   level      value_t      value_o truth
#> 1 mapsection1 Country       Canada       Canada    TP
#> 2 mapsection2 Country       Canada       Canada    TP
#> 3 mapsection3 Country       Canada       Canada    TP
#> 4 mapsection4 Country UnitedStates UnitedStates    TP
#> 5 mapsection5 Country UnitedStates UnitedStates    TP
#> 6 mapsection1  Region      Ontario      Ontario    TP

Then drop the value columns and spread to a wide shape again. You could do this and the joining in one step; breaking into two parts was just easier for explaining.

joined %>%
  select(-starts_with("value")) %>%
  spread(key = level, value = truth)
#>    MapSection Country Region Zone
#> 1 mapsection1      TP     TP   TP
#> 2 mapsection2      TP     TP   TP
#> 3 mapsection3      TP     FN   TN
#> 4 mapsection4      TP     TP   TP
#> 5 mapsection5      TP     TP   FP

Created on 2019-05-31 by the reprex package (v0.3.0)


问:
How do I select the top 10 values based on specific criteria?
I would like to select the top ten products based on revenue, for three different weeks:

The weeks change automatically (for example, this week I have 5/27, but next week it will automatically update to 6/3).

My dataset automatically updates every week and looks as follows:

I've tried using INDEX MATCH and LARGE, but I couldn't figure out how to do it automatically.

I expect the output to be a formula that would automatically update every time my dataset updates by adding additional weeks' revenue.

Any help would be greatly appreciated!

答:
B4:

```<code>={ARRAYFORMULA(INDIRECT("Dataset!"&ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21),
 WEEKNUM(INDIRECT("Dataset!A1:"&ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))),
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)),
 Dataset!1:1, 0),4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)), Dataset!1:1, 0),4))))}
</code>```

B5:

```<code>={ARRAYFORMULA(INDEX(Dataset!B1:1, MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1, COUNTA(Dataset!1:1)-1)), 0))),
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDEX(Dataset!B1:1,
 MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1, COUNTA(Dataset!1:1)-1)), 0)),
 Dataset!1:1, 0), 4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDEX(Dataset!B1:1,
 MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1)), 0)), Dataset!1:1, 0), 4))))}
</code>```

B6:

```<code>={ARRAYFORMULA(INDIRECT("Dataset!"&ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21),
 WEEKNUM(INDIRECT("Dataset!A1:"&ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)))-7,
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))-7,
 Dataset!1:1, 0),4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))-7, Dataset!1:1, 0), 4))))}
</code>```

E5:

```<code>=ARRAYFORMULA({
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(F$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(F$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0),
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(H$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(H$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0),
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(J$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(J$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0)})
</code>```

Body:
B4:

={ARRAYFORMULA(INDIRECT("Dataset!"&ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21),
 WEEKNUM(INDIRECT("Dataset!A1:"&ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))),
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)),
 Dataset!1:1, 0),4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)), Dataset!1:1, 0),4))))}

B5:

={ARRAYFORMULA(INDEX(Dataset!B1:1, MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1, COUNTA(Dataset!1:1)-1)), 0))),
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDEX(Dataset!B1:1,
 MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1, COUNTA(Dataset!1:1)-1)), 0)),
 Dataset!1:1, 0), 4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDEX(Dataset!B1:1,
 MATCH(MAX(MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!B2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1))), MMULT(TRANSPOSE(ROW(
 Dataset!B2:INDEX(Dataset!A2:B, COUNTA(Dataset!A:A)-1)))^0,
 Dataset!B2:INDEX(Dataset!B2:Z, COUNTA(Dataset!A:A)-1,
 COUNTA(Dataset!1:1)-1)), 0)), Dataset!1:1, 0), 4))))}

B6:

={ARRAYFORMULA(INDIRECT("Dataset!"&ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21),
 WEEKNUM(INDIRECT("Dataset!A1:"&ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4)))-7,
 ARRAYFORMULA(SUM(INDIRECT("Dataset!"&ADDRESS(2, MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))-7,
 Dataset!1:1, 0),4)&":"&ADDRESS(ROWS(Dataset!A:A), MATCH(INDIRECT("Dataset!"&
 ADDRESS(1, MATCH(WEEKNUM(TODAY(), 21), WEEKNUM(INDIRECT("Dataset!A1:"&
 ADDRESS(1, COUNTA(Dataset!A1:1), 4)), 21), 0), 4))-7, Dataset!1:1, 0), 4))))}

E5:

=ARRAYFORMULA({
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(F$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(F$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0),
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(H$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(H$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0),
 QUERY({Dataset!$A$2:$A, INDIRECT("Dataset!"&
 ADDRESS(2,                      MATCH(J$3, Dataset!$A$1:$1, 0), 4)&":"&
 ADDRESS(ROWS(Dataset!$A2:$A)+1, MATCH(J$3, Dataset!$A$1:$1, 0), 4))},
 "order by Col2 desc limit 10", 0)})


问:
Navigating embedded Google Apps Script iFrame from the parent
I have a multi-page Web App. I want after login, a user sees the list of his teammate and marks their attendance status. My issue is I can't show that in an iFrame rather than google script original one.

For instance, I wanted to iFrame it to my own web page. it is two days I can't overcome this issue, I read lots of posts in this regard and also tried another app from scratch, but no luck yet.

For clarification, I am redirecting the user inside the frame using render function. So as @theMaster mentioned it is not a multi-page Web App.

here is my doGet and Render functions:

```<code>function doGet(e){
    // Logger.log(e);
    Route.path("login",loadLogin);
    Route.path("admin",loadAdmin);
    Route.path("view",loadView);
    Route.path("form",loadForm);
if (e.parameters.id){
  LastID=e.parameters.id[0];
}
if (e.parameters.t){
  curT=e.parameters.t[0];
}
if (Route[e.parameters.v]) {
  return Route[e.parameters.v]();
} else {
  return render('W-home');
  }
}

function render(file, argObject){
    var page = HtmlService.createTemplateFromFile(file);
    if (argObject){
        var keys = Object.keys(argObject);
        keys.forEach(function (k){
        page[k]=argObject[k];
        });
    }
    var evalPage =page.evaluate();
    // if (!xFrame){return evalPage;};
    return evalPage.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
</code>```

I can go from home page to login page, but after that, even it doesn't let me go to google. In some cases also just returns a blank page inside the frame.

Here is my sample code for the client-side JavaScript.

```<code>function goToForm(EmpNo) {
  var link = "<?!=ScriptApp.getService().getUrl()?>" + "?v=form&id=" + EmpNo[1] + "&t=" + EmpNo[2];
  location.href = link;
  // I tried different way to see if i can conqure this!
  // if (clickBTN= 'a') {
  //   window.open(link, "_self");
  // } if (clickBTN= 'b') {
  //   location.href=link;
  // } if (clickBTN= 'c') {
  //   openNewURLInTheSameWindow(link);
  // }
}
</code>```

I also have two global variables xFrame to set  XframeOptionsMode to allowAll or not and base to switch base target on the HTM pages to "_top" or "_self".

答:
Issue:

You can try

```<code>window.top.location = link;
</code>```

It'll load the link in the top frame. If you are framing the web-app itself in your website, then you should use

```<code>window.parent.parent.location = link;
</code>```

But this won't work because the sandbox prevents navigating other frames in the document. sandbox="allow-top-navigation" only allows top frame navigation and not the intermediate frames. Since the top frame is your site and not script.google.com, it can't be navigated and you'll get the error

Unsafe JavaScript attempt to initiate navigation for frame with URL https://myexamplesite.com... from frame with URL https://*.googleusercontent.com/... The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.

Solution:

Use window.postMessage()

```<code>
==================
|Your site       |<-myexamplesite.com [TOP#0]
|                |
| =============  |
| |GASWebApp  |<-|--script.google.com[Frame#1]
| |           |  |
| |=========  |  |
| ||SandBox|  |  |
| ||User   |<-|--|-- Where your html code is
| ||Frame  |  |  |  (*.googleusercontent.com)
| |=========  |  |   [Frame#2 and #3(Double nested iframe)]
| |           |  |
| =============  |
|                |
|                |
|                |
==================
</code>```

Snippet:

Sandboxed Html:

```
<p><em>Top frame</em>(#0):</p>
<pre class="lang-html prettyprint-override"><code><!-- Frame the Apps script Web-App Frame#1-->
<iframe
  src="https://script.google.com/macros/s/[SCRIPT_DEPLOYMENT_ID]/exec"
  >Loading...</iframe
>
<script type="text/javascript">
  const handleMessage = function(event) {
    if (
      event.origin !==
      'https://[SCRIPT_ORIGIN]script.googleusercontent.com'
    ) {
      alert('Origin Disallowed');
      return;
    }
      //TODO Check syntax of event.data before changing iframe src
      document.querySelector('iframe').src = event.data; //Change #1 Link
  };
  window.addEventListener('message', handleMessage);
</script>
</code>```

References:

Basic GAS webapp structure

postMessage

iFrame

Body:
I have a multi-page Web App. I want after login, a user sees the list of his teammate and marks their attendance status. My issue is I can't show that in an iFrame rather than google script original one.

For instance, I wanted to iFrame it to my own web page. it is two days I can't overcome this issue, I read lots of posts in this regard and also tried another app from scratch, but no luck yet.

For clarification, I am redirecting the user inside the frame using render function. So as @theMaster mentioned it is not a multi-page Web App.

here is my doGet and Render functions:

function doGet(e){
    // Logger.log(e);
    Route.path("login",loadLogin);
    Route.path("admin",loadAdmin);
    Route.path("view",loadView);
    Route.path("form",loadForm);
if (e.parameters.id){
  LastID=e.parameters.id[0];
}
if (e.parameters.t){
  curT=e.parameters.t[0];
}
if (Route[e.parameters.v]) {
  return Route[e.parameters.v]();
} else {
  return render('W-home');
  }
}

function render(file, argObject){
    var page = HtmlService.createTemplateFromFile(file);
    if (argObject){
        var keys = Object.keys(argObject);
        keys.forEach(function (k){
        page[k]=argObject[k];
        });
    }
    var evalPage =page.evaluate();
    // if (!xFrame){return evalPage;};
    return evalPage.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

I can go from home page to login page, but after that, even it doesn't let me go to google. In some cases also just returns a blank page inside the frame.

Here is my sample code for the client-side JavaScript.

function goToForm(EmpNo) {
  var link = "<?!=ScriptApp.getService().getUrl()?>" + "?v=form&id=" + EmpNo[1] + "&t=" + EmpNo[2];
  location.href = link;
  // I tried different way to see if i can conqure this!
  // if (clickBTN= 'a') {
  //   window.open(link, "_self");
  // } if (clickBTN= 'b') {
  //   location.href=link;
  // } if (clickBTN= 'c') {
  //   openNewURLInTheSameWindow(link);
  // }
}

I also have two global variables xFrame to set  XframeOptionsMode to allowAll or not and base to switch base target on the HTM pages to "_top" or "_self".

Body:
Issue:

You can try

window.top.location = link;

It'll load the link in the top frame. If you are framing the web-app itself in your website, then you should use

window.parent.parent.location = link;

But this won't work because the sandbox prevents navigating other frames in the document. sandbox="allow-top-navigation" only allows top frame navigation and not the intermediate frames. Since the top frame is your site and not script.google.com, it can't be navigated and you'll get the error

Unsafe JavaScript attempt to initiate navigation for frame with URL https://myexamplesite.com... from frame with URL https://*.googleusercontent.com/... The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.

Solution:

Use window.postMessage()

==================
|Your site       |<-myexamplesite.com [TOP#0]
|                |
| =============  |
| |GASWebApp  |<-|--script.google.com[Frame#1]
| |           |  |
| |=========  |  |
| ||SandBox|  |  |
| ||User   |<-|--|-- Where your html code is
| ||Frame  |  |  |  (*.googleusercontent.com)
| |=========  |  |   [Frame#2 and #3(Double nested iframe)]
| |           |  |
| =============  |
|                |
|                |
|                |
==================

Snippet:

Sandboxed Html:

<script>
if(window.parent.parent !== window.top){ //if #1 !== top
  //Framed in a another web-app
  //TODO Use proper target origin instead of *
   window.parent.parent.parent.postMessage("[FRAME#1_LINK_TO_CHANGE]","*");//Post to #0
}
</script>

Top frame(#0):

<!-- Frame the Apps script Web-App Frame#1-->
<iframe
  src="https://script.google.com/macros/s/[SCRIPT_DEPLOYMENT_ID]/exec"
  >Loading...</iframe
>
<script type="text/javascript">
  const handleMessage = function(event) {
    if (
      event.origin !==
      'https://[SCRIPT_ORIGIN]script.googleusercontent.com'
    ) {
      alert('Origin Disallowed');
      return;
    }
      //TODO Check syntax of event.data before changing iframe src
      document.querySelector('iframe').src = event.data; //Change #1 Link
  };
  window.addEventListener('message', handleMessage);
</script>

References:

Basic GAS webapp structure

postMessage

iFrame


问:
How to mock a method of a third party package
I had a simple function which connects to mongoDB and create a new document.
Now how do I mock the methods of the imported mongo package while unit testing.

Ive tried to mock GinContext by monkeypatching.

But unable to proceed with mocking the actual mongoClient as the package is imported.

func CreateUser(c GinContext) {
    var userdetail UserDetails
    binderr := c.ShouldBindJSON(&userdetail)
    fmt.Println(binderr)
    if binderr != nil {
        c.JSON(500, gin.H{
            "message": "Input payload not matching",
            "error":   binderr,
        })
        return
    }

    //-- Client if of type *mongo.Client.

        //-- How do I mock the Client.Database, Client.Database.Connection

    collection := Client.Database("demo").Collection("users")
    ctx, err1 := context.WithTimeout(context.Background(), 10*time.Second)
    if err1 != nil {
    }
    response, err2 := collection.InsertOne(ctx, userdetail)
    if err2 != nil {
        log.Println("Some error inserting the document")
    }
    fmt.Println(response.InsertedID)
    c.JSON(200, gin.H{
        "message": "User created successfully",
    })
}
```

Expected: I should be able to mock or stub Client and provide dummy functionality. Just like in nodeJS we do

spyOn(Client,'Database').and.return(Something)

答:
Every time I'm wondering "how to mock a method", this is mostly related to my code architecture. Not being able to test easily some code means, most of time, that the code is poorly designed and/or too coupled to the used libraries/frameworks. Here, you want to mock Mongo connection only because your code is too tightly related to Mongo (in the CreateUser function). Refactoring could help you to test your code (without any Mongo connection).

I've experienced that using interfaces and dependency injection simplifies
the testing process in Go, and clarifies the architecture. Here is my attempt to help you test your application.

Code refactoring

First, define what you want to do with an interface. Here, you're inserting users, so let's do a UserInserter interface, with a single method for now (Insert, to insert a single user) :

type UserInserter interface {
    Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error)
}
```

<p>In the code you have provided, you are only using the <code>insertedID</code>, so you probably only need it as output of this <code>Insert</code> method (and an optional error if something gone wrong). <code>insertedID</code> is defined as an <code>interface{}</code> here, but feel free to change to whatever you want.</p>

<p>Then, let's modify your <code>CreateUser</code> method and inject this <code>UserInserter</code> <strong>as a parameter</strong> :</p>

<pre class="lang-golang prettyprint-override"><code>func CreateUser(c *gin.Context, userInserter UserInserter) {
    var userdetail UserDetails
    binderr := c.ShouldBindJSON(&userdetail)
    fmt.Println(binderr)
    if binderr != nil {
        c.JSON(500, gin.H{
            "message": "Input payload not matching",
            "error":   binderr,
        })
        return
    }

    // this is the modified part
    insertedID, err2 := userInserter.Insert(c, userdetail)
    if err2 != nil {
        log.Println("Some error inserting the document")
    }
    fmt.Println(insertedID)

    c.JSON(200, gin.H{
        "message": fmt.Sprintf("User %s created successfully", insertedID),
    })
}
</code>```

This method could be refactored but, to avoid any confusion, I will not touch it.

userInserter.Insert(c, userdetail) replaces here the Mongo dependency in this method by injecting userInserter.

You can now implement your UserInserter interface with the backend of your choice (Mongo in your case). Insertion into Mongo needs a Collection object (the collection we are inserting the user in), so let's add this as an attribute :

type MongoUserInserter struct {
    collection *mongo.Collection
}
```

<p>Implementation of <code>Insert</code> method follows (call <code>InsertOne</code> method on <code>*mongo.Collection</code>) :</p>

<pre class="lang-golang prettyprint-override"><code>func (i MongoUserInserter) Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error) {
    response, err := i.collection.InsertOne(ctx, userDetails)
    return response.InsertedID, err
}
</code>```

This implementation could be in a separated package and should be tested separately.

Once implemented, you can use MongoUserInserter in your main application, where Mongo is the backend. MongoUserInserter is initialized in the main function, and injected in the CreateUser method. Router setup have been separated (also for testing purpose) :

func setupRouter(userInserter UserInserter) *gin.Engine {
    router := gin.Default()

    router.POST("/createUser", func(c *gin.Context) {
        CreateUser(c, userInserter)
    })

    return router
}

func main() {
    client, _ := mongo.NewClient()
    collection := client.Database("demo").Collection("users")
    userInserter := MongoUserInserter{collection: collection}

    router := setupRouter(userInserter)
    router.Run(":8080")
}
```

<p>Note that if some day you want to change the backend, you will only
need to change the <code>userInserter</code> in the main function!</p>

<h3>Tests</h3>

<p>From a tests perspective, it is now easier to test because we can create a fake <code>UserInserter</code>, like :</p>

<pre class="lang-golang prettyprint-override"><code>type FakeUserInserter struct{}

func (_ FakeUserInserter) Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error) {
    return userDetails.Name, nil
}
</code>```

(I supposed here UserDetails have an attribute Name).

If you really want to mock this interface, you can take a look at GoMock. In this case though, I'm not sure using a mock framework is required.

And now we can test our CreateUser method with a simple HTTP testing framework (see https://github.com/gin-gonic/gin#testing), without needing a Mongo connection or mocking it.

import (
    "bytes"
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/stretchr/testify/assert"
)

func TestCreateUser(t *testing.T) {
    userInserter := FakeUserInserter{}
    router := setupRouter(userInserter)

    w := httptest.NewRecorder()
    body := []byte(`{"name": "toto"}`)
    req, _ := http.NewRequest("POST", "/createUser", bytes.NewBuffer(body))
    router.ServeHTTP(w, req)

    assert.Equal(t, 200, w.Code)
    assert.Equal(t, `{"message":"User toto created successfully"}`, w.Body.String())
}
```

Note that this does not exempt to also test Insert method of MongoUserInserter, but separately : here, this test covers CreateUser, not the Insert method.

Body:
I had a simple function which connects to mongoDB and create a new document.
Now how do I mock the methods of the imported mongo package while unit testing.

Ive tried to mock GinContext by monkeypatching.

But unable to proceed with mocking the actual mongoClient as the package is imported.

func CreateUser(c GinContext) {
    var userdetail UserDetails
    binderr := c.ShouldBindJSON(&userdetail)
    fmt.Println(binderr)
    if binderr != nil {
        c.JSON(500, gin.H{
            "message": "Input payload not matching",
            "error":   binderr,
        })
        return
    }

    //-- Client if of type *mongo.Client.

        //-- How do I mock the Client.Database, Client.Database.Connection

    collection := Client.Database("demo").Collection("users")
    ctx, err1 := context.WithTimeout(context.Background(), 10*time.Second)
    if err1 != nil {
    }
    response, err2 := collection.InsertOne(ctx, userdetail)
    if err2 != nil {
        log.Println("Some error inserting the document")
    }
    fmt.Println(response.InsertedID)
    c.JSON(200, gin.H{
        "message": "User created successfully",
    })
}

Expected: I should be able to mock or stub Client and provide dummy functionality. Just like in nodeJS we do

spyOn(Client,'Database').and.return(Something)

Body:
Every time I'm wondering "how to mock a method", this is mostly related to my code architecture. Not being able to test easily some code means, most of time, that the code is poorly designed and/or too coupled to the used libraries/frameworks. Here, you want to mock Mongo connection only because your code is too tightly related to Mongo (in the CreateUser function). Refactoring could help you to test your code (without any Mongo connection).

I've experienced that using interfaces and dependency injection simplifies
the testing process in Go, and clarifies the architecture. Here is my attempt to help you test your application.

Code refactoring

First, define what you want to do with an interface. Here, you're inserting users, so let's do a UserInserter interface, with a single method for now (Insert, to insert a single user) :

type UserInserter interface {
    Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error)
}

In the code you have provided, you are only using the insertedID, so you probably only need it as output of this Insert method (and an optional error if something gone wrong). insertedID is defined as an interface{} here, but feel free to change to whatever you want.

Then, let's modify your CreateUser method and inject this UserInserter as a parameter :

func CreateUser(c *gin.Context, userInserter UserInserter) {
    var userdetail UserDetails
    binderr := c.ShouldBindJSON(&userdetail)
    fmt.Println(binderr)
    if binderr != nil {
        c.JSON(500, gin.H{
            "message": "Input payload not matching",
            "error":   binderr,
        })
        return
    }

    // this is the modified part
    insertedID, err2 := userInserter.Insert(c, userdetail)
    if err2 != nil {
        log.Println("Some error inserting the document")
    }
    fmt.Println(insertedID)

    c.JSON(200, gin.H{
        "message": fmt.Sprintf("User %s created successfully", insertedID),
    })
}

This method could be refactored but, to avoid any confusion, I will not touch it.

userInserter.Insert(c, userdetail) replaces here the Mongo dependency in this method by injecting userInserter.

You can now implement your UserInserter interface with the backend of your choice (Mongo in your case). Insertion into Mongo needs a Collection object (the collection we are inserting the user in), so let's add this as an attribute :

type MongoUserInserter struct {
    collection *mongo.Collection
}

Implementation of Insert method follows (call InsertOne method on *mongo.Collection) :

func (i MongoUserInserter) Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error) {
    response, err := i.collection.InsertOne(ctx, userDetails)
    return response.InsertedID, err
}

This implementation could be in a separated package and should be tested separately.

Once implemented, you can use MongoUserInserter in your main application, where Mongo is the backend. MongoUserInserter is initialized in the main function, and injected in the CreateUser method. Router setup have been separated (also for testing purpose) :

func setupRouter(userInserter UserInserter) *gin.Engine {
    router := gin.Default()

    router.POST("/createUser", func(c *gin.Context) {
        CreateUser(c, userInserter)
    })

    return router
}

func main() {
    client, _ := mongo.NewClient()
    collection := client.Database("demo").Collection("users")
    userInserter := MongoUserInserter{collection: collection}

    router := setupRouter(userInserter)
    router.Run(":8080")
}

Note that if some day you want to change the backend, you will only
need to change the userInserter in the main function!

Tests

From a tests perspective, it is now easier to test because we can create a fake UserInserter, like :

type FakeUserInserter struct{}

func (_ FakeUserInserter) Insert(ctx context.Context, userDetails UserDetails) (insertedID interface{}, err error) {
    return userDetails.Name, nil
}

(I supposed here UserDetails have an attribute Name).

If you really want to mock this interface, you can take a look at GoMock. In this case though, I'm not sure using a mock framework is required.

And now we can test our CreateUser method with a simple HTTP testing framework (see https://github.com/gin-gonic/gin#testing), without needing a Mongo connection or mocking it.

import (
    "bytes"
    "net/http"
    "net/http/httptest"
    "testing"

    "github.com/stretchr/testify/assert"
)

func TestCreateUser(t *testing.T) {
    userInserter := FakeUserInserter{}
    router := setupRouter(userInserter)

    w := httptest.NewRecorder()
    body := []byte(`{"name": "toto"}`)
    req, _ := http.NewRequest("POST", "/createUser", bytes.NewBuffer(body))
    router.ServeHTTP(w, req)

    assert.Equal(t, 200, w.Code)
    assert.Equal(t, `{"message":"User toto created successfully"}`, w.Body.String())
}

Note that this does not exempt to also test Insert method of MongoUserInserter, but separately : here, this test covers CreateUser, not the Insert method.


问:
Run Powershell Command from Oracle Procedure
I need to print pdf documents to my network printer from my android studio application. I want to print the pdf as is with all images and formatting, however, the solutions I have found only allow for the extraction and printing of text from the pdf.

I have also seen solutions mentioning tools like Ghostscript etc which are supposed to convert the pdf to a postscript file, but these tools do not work with Android Studio or at-least I haven't figured out how to integrate them into my application. I cannot pay for tools like jPDFPrint which does exactly what I need.

I started thinking about a work around and came upon the idea of sending my pdf as a blob to my oracle database and invoke a power shell command from a procedure to print it to a specific printer.

I've created and tested the below command to print to my network printer from my PC which works great.

```<code>    Start-Process -FilePath “c:\test.pdf” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill
</code>```

Now I need help with the oracle part. Is it possible to invoke or run a powershell command from within oracle 12c and pass it the pdf blob as well as the printer name?

答:
To extract the BLOB to a PDF.

Create you system folder, eg c:\printthis.

Then create the Oracle directory object mapped to this folder:

```<code>CREATE OR REPLACE DIRECTORY print_dir AS 'C:\print_this';

GRANT READ WRITE ON DIRECTORY print_dir TO PUBLIC;
</code>```

This procedure to extract the BLOB to a file.

```<code>CREATE OR REPLACE PROCEDURE extract_pdf ( p_id IN VARCHAR2 ) AS
   CURSOR c1 IS
      SELECT doc_blob, doc_name
      FROM doc_table
      WHERE doc_id = p_id;
   r1         c1%ROWTYPE;
   v_size     NUMBER( 5,0) := 32000;
   v_len      NUMBER(38,0);
   v_buffer   RAW(32000);
   v_file     UTL_FILE.FILE_TYPE;
BEGIN
   OPEN c1;
   FETCH c1 INTO r1;
   v_file  := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name, 'wb', 32760 );
   v_start := 1;
   v_len   := DBMS_LOB.GETLENGTH( r.bbl_fic );
   WHILE v_start <= v_len LOOP
      DBMS_LOB.READ(
             r.bbl_fic,
             LEAST( v_len - v_start + 1, v_size ),
             v_start,
             v_buffer
           );
      UTL_FILE.PUT_RAW( v_file, v_buffer );
      UTL_FILE.FFLUSH( v_file );
      v_start := v_start + v_size;
    END LOOP;
    UTL_FILE.FCLOSE( v_file );
--  Write the CMD file
    v_file := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name || '.bat', 'w' );
    UTL_FILE.PUT_LINE(     'Start-Process -FilePath “c:\print_this\' || r1.doc_name || '” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill' );
    UTL_FILE.CLOSE(v_file);
END;
/
</code>```

A Windows At job that runs, polls the c:\print_this folder for files and runs the .bat command, then deletes it.

```<code>@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (c:\print_this\*.bat) do (
  echo "Name: %%f"
  powershell %%f
  del %%f
)
</code>```

The question remains of how to stitch this together. Your Android app calls your procedure to store the PDF as a BLOB. It must also be able to call the procedure suggested above to extract the saved BLOB to a database server file, so this procedure to extract the ODF AND create the print bat script is called after the save BLOB.

The Task Scheduler job polls the directory for the bat scripts, runs them deletes them.

You cannot directly issue a command to the server host from within Oracle. You can use DBMS_SCHEDULER. In the above example, the job would take the doc_id as a parameter, and execute this via DBMS_SCHEDULER.RUN_JOB. I cant remember how to do this precisely, but I hope my other suggestion with the Task Scheduler in Windows is fruitful for you.

Body:
I need to print pdf documents to my network printer from my android studio application. I want to print the pdf as is with all images and formatting, however, the solutions I have found only allow for the extraction and printing of text from the pdf.

I have also seen solutions mentioning tools like Ghostscript etc which are supposed to convert the pdf to a postscript file, but these tools do not work with Android Studio or at-least I haven't figured out how to integrate them into my application. I cannot pay for tools like jPDFPrint which does exactly what I need.

I started thinking about a work around and came upon the idea of sending my pdf as a blob to my oracle database and invoke a power shell command from a procedure to print it to a specific printer.

I've created and tested the below command to print to my network printer from my PC which works great.

    Start-Process -FilePath “c:\test.pdf” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill

Now I need help with the oracle part. Is it possible to invoke or run a powershell command from within oracle 12c and pass it the pdf blob as well as the printer name?

Body:
To extract the BLOB to a PDF.

Create you system folder, eg c:\printthis.

Then create the Oracle directory object mapped to this folder:

CREATE OR REPLACE DIRECTORY print_dir AS 'C:\print_this';

GRANT READ WRITE ON DIRECTORY print_dir TO PUBLIC;

This procedure to extract the BLOB to a file.

CREATE OR REPLACE PROCEDURE extract_pdf ( p_id IN VARCHAR2 ) AS
   CURSOR c1 IS
      SELECT doc_blob, doc_name
      FROM doc_table
      WHERE doc_id = p_id;
   r1         c1%ROWTYPE;
   v_size     NUMBER( 5,0) := 32000;
   v_len      NUMBER(38,0);
   v_buffer   RAW(32000);
   v_file     UTL_FILE.FILE_TYPE;
BEGIN
   OPEN c1;
   FETCH c1 INTO r1;
   v_file  := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name, 'wb', 32760 );
   v_start := 1;
   v_len   := DBMS_LOB.GETLENGTH( r.bbl_fic );
   WHILE v_start <= v_len LOOP
      DBMS_LOB.READ(
             r.bbl_fic,
             LEAST( v_len - v_start + 1, v_size ),
             v_start,
             v_buffer
           );
      UTL_FILE.PUT_RAW( v_file, v_buffer );
      UTL_FILE.FFLUSH( v_file );
      v_start := v_start + v_size;
    END LOOP;
    UTL_FILE.FCLOSE( v_file );
--  Write the CMD file
    v_file := UTL_FILE.FOPEN('PRINT_DIR', r1.doc_name || '.bat', 'w' );
    UTL_FILE.PUT_LINE(     'Start-Process -FilePath “c:\print_this\' || r1.doc_name || '” –Verb PrintTo '\\PrintServer\PrinterName' -PassThru | %{sleep 10;$_} | kill' );
    UTL_FILE.CLOSE(v_file);
END;
/

A Windows At job that runs, polls the c:\print_this folder for files and runs the .bat command, then deletes it.

@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (c:\print_this\*.bat) do (
  echo "Name: %%f"
  powershell %%f
  del %%f
)

The question remains of how to stitch this together. Your Android app calls your procedure to store the PDF as a BLOB. It must also be able to call the procedure suggested above to extract the saved BLOB to a database server file, so this procedure to extract the ODF AND create the print bat script is called after the save BLOB.

The Task Scheduler job polls the directory for the bat scripts, runs them deletes them.

You cannot directly issue a command to the server host from within Oracle. You can use DBMS_SCHEDULER. In the above example, the job would take the doc_id as a parameter, and execute this via DBMS_SCHEDULER.RUN_JOB. I cant remember how to do this precisely, but I hope my other suggestion with the Task Scheduler in Windows is fruitful for you.


问:
Is cursor over element (on page load)?
I have a .hover() action assigned to an element to hide/show something depending on the cursor being over it. The problem I am running into is that when the page loads and the cursor is OVER the element it doesn't register as being over because its not firing the mouseenter event.

Is there a another way to tell if the cursor is over a desired element?

答: Script to get mouse coordinates on load</p>

Title: Is cursor over element (on page load)?

Body: Script to get mouse coordinates on load


问:
Python 3 - Decoding bytes that contains a mix of hex and unicode
I'm porting a codebase for the Lasersaur laser cutter from Python2 to Python3, and I'm having a bit of trouble decoding the serial data coming in from the onboard Arduino. The data comes in as a byte stream that mixes hex and unicode data, like so:

```<code>bytes: b'AC\xfb\xff\xff\xbfx\x85\x80\x80\xc0y\x80\x80\x80\xc0z'
data:  A C 251 255 255 x 133 128 128 y 128 128 128 z
</code>```

Python2 was able to steamroll over the mixed-type data, and read in the serial data as a string of characters, after which ord() was used to determine if the character represented data or a status character. You can see how this is implemented in the original Python2 code starting at line 367 here.

```<code>ord(data): 65 67 251 255 255 120 133 128 128 121 128 128 128 122
</code>```

Python3 is more stringent about encodings, and throws me the following error when I try bytes.decode('utf-8'), because it gets to the first hex data b'x\fb' and chokes because it's a different format. Messing around with a few different codecs doesn't give any better results.

```<code>UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfb in position 2: invalid start byte
</code>```

I found this StackOverflow thread which addresses what I need pretty much exactly, but it seems that the error handling in Python 3 no longer works the same, and throws me this error when I try the solution there: TypeError: 'UnicodeDecodeError' object is not subscriptable.

I could modify the onboard code on the Arduino in order to get a saner serial encoding, but the main reason I'm porting to Python3 is that I can't get the right (read: old) Python2 libraries in order to execute the code and I don't want to run into the scenario where I inadvertently get to a state where it's impossible to communicate with the onboard arduino.

What I'd like to do is mimic the original functionality as closely as possible, and get out either a string of characters that I can call ord() on, or a mix of characters and numbers in a list. I'm a bit lost on how to do this.

答:
You don't have 'mixed' data, you have a bytes object. When you print it, Python represents all bytes whose value corresponds to a letter in ASCII as a letter, in order to help us identify text among it.

You can access any individual byte as an integer by indexing:

```<code>data = b'AC\xfb\xff\xff\xbfx\x85\x80\x80\xc0y\x80\x80\x80\xc0z'

print(data[0])
# 65
</code>```

The value gets returned as an integer. (here, 65, which corresponds to 'A' in ASCII, hence its representation in the bytes string.)

So, a simple way to convert the bytes to a list of integers would be:

```<code>data_as_int = [b for b in data]
</code>```

or even simpler:

```<code>data_as_int = list(data)
</code>```

which gives us:

```<code>print(data_as_int)
# [65, 67, 251, 255, 255, 191, 120, 133, 128, 128, 192, 121, 128, 128, 128, 192, 122]
</code>```

About your idea of converting the bytes to a string, in order to use ord afterwards: you can do it, but you have to use an encoding like latin1 in which each byte corresponds to one character - which is not the case with utf8.
So, you could have done something like:

```<code>data_as_int = [ord(c) for c in data.decode('latin1')]
</code>```

but this is less direct than the above solution.

Body:
I'm porting a codebase for the Lasersaur laser cutter from Python2 to Python3, and I'm having a bit of trouble decoding the serial data coming in from the onboard Arduino. The data comes in as a byte stream that mixes hex and unicode data, like so:

bytes: b'AC\xfb\xff\xff\xbfx\x85\x80\x80\xc0y\x80\x80\x80\xc0z'
data:  A C 251 255 255 x 133 128 128 y 128 128 128 z

Python2 was able to steamroll over the mixed-type data, and read in the serial data as a string of characters, after which ord() was used to determine if the character represented data or a status character. You can see how this is implemented in the original Python2 code starting at line 367 here.

ord(data): 65 67 251 255 255 120 133 128 128 121 128 128 128 122

Python3 is more stringent about encodings, and throws me the following error when I try bytes.decode('utf-8'), because it gets to the first hex data b'x\fb' and chokes because it's a different format. Messing around with a few different codecs doesn't give any better results.

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfb in position 2: invalid start byte

I found this StackOverflow thread which addresses what I need pretty much exactly, but it seems that the error handling in Python 3 no longer works the same, and throws me this error when I try the solution there: TypeError: 'UnicodeDecodeError' object is not subscriptable.

I could modify the onboard code on the Arduino in order to get a saner serial encoding, but the main reason I'm porting to Python3 is that I can't get the right (read: old) Python2 libraries in order to execute the code and I don't want to run into the scenario where I inadvertently get to a state where it's impossible to communicate with the onboard arduino.

What I'd like to do is mimic the original functionality as closely as possible, and get out either a string of characters that I can call ord() on, or a mix of characters and numbers in a list. I'm a bit lost on how to do this.

Body:
You don't have 'mixed' data, you have a bytes object. When you print it, Python represents all bytes whose value corresponds to a letter in ASCII as a letter, in order to help us identify text among it.

You can access any individual byte as an integer by indexing:

data = b'AC\xfb\xff\xff\xbfx\x85\x80\x80\xc0y\x80\x80\x80\xc0z'

print(data[0])
# 65

The value gets returned as an integer. (here, 65, which corresponds to 'A' in ASCII, hence its representation in the bytes string.)

So, a simple way to convert the bytes to a list of integers would be:

data_as_int = [b for b in data]

or even simpler:

data_as_int = list(data)

which gives us:

print(data_as_int)
# [65, 67, 251, 255, 255, 191, 120, 133, 128, 128, 192, 121, 128, 128, 128, 192, 122]

About your idea of converting the bytes to a string, in order to use ord afterwards: you can do it, but you have to use an encoding like latin1 in which each byte corresponds to one character - which is not the case with utf8.
So, you could have done something like:

data_as_int = [ord(c) for c in data.decode('latin1')]

but this is less direct than the above solution.


问:
Timeout error for element already clicked
I am getting below exception even when my element has already been clicked and i am navigated to next page.

Caused by: org.openqa.selenium.TimeoutException: Expected condition
  failed: waiting for element to be clicked: [[ChromeDriver: chrome on
  XP (56f040029c23126b0087ff1dfa82369e)] -> xpath:
  //*[@id='login']/app-root/app-caf-login/div/div/div[2]/form/div[3]/div/div/button]
  (tried for 10 second(s) with 500 milliseconds interval)

Verifying XPAth but since element is already clicked them not sure why error is coming.

Description: Click the Sign In Button

```<code> action: org.getopentest.selenium.Click
        args:
          locator: { xpath: "//*[@id='login']/app-root/app-caf-login/div/div/div[2]/form/div[3]/div/div/button" }
</code>```

Description: Pause for 60 second

```<code>action: org.getopentest.selenium.ActionsPause
        args:
          durationMs: "60000"
</code>```

Expected : no error should be there

答:
As described in this answer make sure you don't use the sendEnter: true argument with any of the SendKeys actions. When you pass sendEnter: true , the action will "press" the enter key after sending the keys to the textbox element. So basically, in the test you showed, the first action will input the username and then press enter, thus trying to log in without a password, which will of course fail.

Also, you are using the ActionsPause keyword incorrectly (more info here). If you want to introduce a delay in your test, you can use the $delay() API, but you very rarely need to do this with OpenTest, since synchronization is built-in, meaning all test actions that perform some work on a UI element know how to wait for that element to be available before doing the work.

Body:
I am getting below exception even when my element has already been clicked and i am navigated to next page.

Caused by: org.openqa.selenium.TimeoutException: Expected condition
  failed: waiting for element to be clicked: [[ChromeDriver: chrome on
  XP (56f040029c23126b0087ff1dfa82369e)] -> xpath:
  //*[@id='login']/app-root/app-caf-login/div/div/div[2]/form/div[3]/div/div/button]
  (tried for 10 second(s) with 500 milliseconds interval)

Verifying XPAth but since element is already clicked them not sure why error is coming.

Description: Click the Sign In Button

 action: org.getopentest.selenium.Click
        args:
          locator: { xpath: "//*[@id='login']/app-root/app-caf-login/div/div/div[2]/form/div[3]/div/div/button" }

Description: Pause for 60 second

action: org.getopentest.selenium.ActionsPause
        args:
          durationMs: "60000"

Expected : no error should be there


问:
tkinter not printing until the window is closed
Here is a minimal example in which left-cliking with the mouse creates a popup window with several choices. Upon selection, the popup is destroyed and the selection is printed.

import tkinter as tk

class Interface(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.can = tk.Canvas(self,background="green",width = 500, height = 500)
        self.can.pack()
        self.bind('<Button-1>', self.choice)

    def choice(self, event):
        popup = tk.Toplevel()
        popup.attributes('-topmost', 'true')
        var = tk.IntVar()
        tk.Radiobutton(popup, text="Zero", value=0, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="0ne", value=1, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="Confirm", fg="red", indicator=0,
                       command=lambda:popup.destroy()).pack()
        popup.mainloop()
        print("choice:", var.get())

main = Interface()
main.mainloop()
```

It almost works, however it is only printed after the main window is closed.
In addition I don't understand why some of the buttons seem already selected.

[Python 3.7, Windows 10]

答:
I'm not completely sure why your code doesn't work, but think it's got something to do with there effectively being two mainloop()s running — one "nested" inside the the other — so ending the inner one isn't allowing the next line in the choice() method to execute until the outer one for the main window also ends.

Regardless of whether that explanation is true or not, a way to workaround the issue is to define the callback function separately to make it easy to put multiple statements in it, then put both the popup destroy() and the print() call in that:

```<code>import tkinter as tk

class Interface(tk.Tk):
    def __init__(self):
        super().__init__()
        self.can = tk.Canvas(self, background="green", width=500, height=500)
        self.can.pack()
        self.bind('<Button-1>', self.choice)

    def choice(self, event):
        popup = tk.Toplevel()
        popup.attributes('-topmost', 'true')
        var = tk.IntVar()

        def callback():
            popup.destroy()
            print("choice:", var.get())

        tk.Radiobutton(popup, text="Zero", value=0, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="0ne", value=1, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="Confirm", fg="red", indicator=0,
                       command=callback).pack()
        popup.mainloop()

main = Interface()
main.mainloop()
</code>```

Body:
Here is a minimal example in which left-cliking with the mouse creates a popup window with several choices. Upon selection, the popup is destroyed and the selection is printed.

import tkinter as tk

class Interface(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.can = tk.Canvas(self,background="green",width = 500, height = 500)
        self.can.pack()
        self.bind('<Button-1>', self.choice)

    def choice(self, event):
        popup = tk.Toplevel()
        popup.attributes('-topmost', 'true')
        var = tk.IntVar()
        tk.Radiobutton(popup, text="Zero", value=0, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="0ne", value=1, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="Confirm", fg="red", indicator=0,
                       command=lambda:popup.destroy()).pack()
        popup.mainloop()
        print("choice:", var.get())

main = Interface()
main.mainloop()

It almost works, however it is only printed after the main window is closed.
In addition I don't understand why some of the buttons seem already selected.

[Python 3.7, Windows 10]

Body:
I'm not completely sure why your code doesn't work, but think it's got something to do with there effectively being two mainloop()s running — one "nested" inside the the other — so ending the inner one isn't allowing the next line in the choice() method to execute until the outer one for the main window also ends.

Regardless of whether that explanation is true or not, a way to workaround the issue is to define the callback function separately to make it easy to put multiple statements in it, then put both the popup destroy() and the print() call in that:

import tkinter as tk

class Interface(tk.Tk):
    def __init__(self):
        super().__init__()
        self.can = tk.Canvas(self, background="green", width=500, height=500)
        self.can.pack()
        self.bind('<Button-1>', self.choice)

    def choice(self, event):
        popup = tk.Toplevel()
        popup.attributes('-topmost', 'true')
        var = tk.IntVar()

        def callback():
            popup.destroy()
            print("choice:", var.get())

        tk.Radiobutton(popup, text="Zero", value=0, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="0ne", value=1, variable=var, indicator=0).pack()
        tk.Radiobutton(popup, text="Confirm", fg="red", indicator=0,
                       command=callback).pack()
        popup.mainloop()

main = Interface()
main.mainloop()


问:
ngx- date picker not showing in angular6 form
I am trying to import the ngx Bootstrap datepicker in my Angular6 Application for that I followed the following steps

to npm install ngx-bootstrap

npm install ngx-bootstrap --save

Installed bootstrap 4

npm install bootstrap@4 --save

In angular.json file and specify the path to the Bootstrap stylesheet (bootstrap.min.css) in the styles property

```<code>  "styles": [

            "src/styles.css",
           "node_modules/bootstrap/dist/css/bootstrap.min.css",
           "node_modules/ngx-bootstrap/datepicker/bs-datepicker.css"

        ],
</code>```

For Using ngx-bootstrap datepicker in Angular :

In app.module.ts file, imported BsDatepickerModule

```<code>import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { FormGroup } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StudentParentRegistrationComponent } from './student-parent-registration/student-parent-registration.component';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
@NgModule({
  declarations: [
    AppComponent,
    StudentParentRegistrationComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule,
    BsDatepickerModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
</code>```

html file

```<code><nav class="navbar navbar-expand-lg">Header
</nav>
<div class="container">
  <h2 class="text-center">Registration</h2>
  <h3>Student Registration</h3>

  <div class="row">
    <div class="col-sm-6">
      <div class="form-group">
        <label for="usn" class="control-label">USN</label>
        <input type="usn" class="form-control" id="usn" name="usn" placeholder="USN">
      </div>
    </div>
    <div class="col-sm-6">
      <div class="form-group">
        <label for="firstName" class="control-label">First Name</label>
        <input type="firstName" class="form-control" id="firstName" name="firstName" placeholder="FirstName">
      </div>
    </div>
</div>

<div class="row">
    <div class="col-sm-6">
        <div class="form-group">
<label for="dateOfBirth" class="control-label">Date Of Birth</label>
<input type="text" class="form-control" id="dateOfBirth" name="dateOfBirth" bsDatePicker [(ngModel)]="dateOfBirth" placeholder="DateOfBirth">
</div>
</div>
</div>

</div>
<div class="card-footer">
  footer
</div>
</code>```

After following these steps, date picker not showing. Anybody please help me to solve this.

答:
you need to call the show method.

you can call it directly in the template like so:

```<code><input type="text" class="form-control" id="dateOfBirth" name="dateOfBirth" bsDatePicker #dp="bsDatepicker" [(ngModel)]="dateOfBirth" placeholder="DateOfBirth">

// call the dp.show() method either by attaching the click event on the input or add a button alongside it
</code>```

Alternatively inject it in the component or service and call the method within

Body:
I am trying to import the ngx Bootstrap datepicker in my Angular6 Application for that I followed the following steps

to npm install ngx-bootstrap

npm install ngx-bootstrap --save

Installed bootstrap 4

npm install bootstrap@4 --save

In angular.json file and specify the path to the Bootstrap stylesheet (bootstrap.min.css) in the styles property

  "styles": [

            "src/styles.css",
           "node_modules/bootstrap/dist/css/bootstrap.min.css",
           "node_modules/ngx-bootstrap/datepicker/bs-datepicker.css"

        ],

For Using ngx-bootstrap datepicker in Angular :

In app.module.ts file, imported BsDatepickerModule

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import { FormGroup } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StudentParentRegistrationComponent } from './student-parent-registration/student-parent-registration.component';
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
@NgModule({
  declarations: [
    AppComponent,
    StudentParentRegistrationComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule,
    BsDatepickerModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

html file

Header

Registration

Student Registration

        USN
        <input type="usn" class="form-control" id="usn" name="usn" placeholder="USN">

        First Name
        <input type="firstName" class="form-control" id="firstName" name="firstName" placeholder="FirstName">

Date Of Birth
<input type="text" class="form-control" id="dateOfBirth" name="dateOfBirth" bsDatePicker [(ngModel)]="dateOfBirth" placeholder="DateOfBirth">

  footer

After following these steps, date picker not showing. Anybody please help me to solve this.

Body:
you need to call the show method.

you can call it directly in the template like so:

<input type="text" class="form-control" id="dateOfBirth" name="dateOfBirth" bsDatePicker #dp="bsDatepicker" [(ngModel)]="dateOfBirth" placeholder="DateOfBirth">

// call the dp.show() method either by attaching the click event on the input or add a button alongside it

Alternatively inject it in the component or service and call the method within


问:
What's the difference between URL.standardized and URL.absoluteURL?
In Swift's URL class, there are .standardized and .absoluteURL properties (.standardizedURL and .absoluteURL, and .URLByStandardizingPath in Objective-C's NSURL). There's also .standardizedFileURL.

I have no idea what the difference is between all these, but there must be one since they provide all of them, right? I mean clearly the .standardizedFileURL is meant to only deal with file URLs, but other than that (for instance, if all are called on a file URL), what's the difference?

From the above-linked docs:

Swift

standardized

Returns a URL with any instances of “..” or “.” removed from its path.

absoluteURL

Returns the absolute URL.

Discussion

If the URL is itself absolute, this will return self.

standardizedFileURL

Standardizes the path of a file URL.

Discussion

If the isFileURL is false, this method returns self.

Objective-C

standardizedURL

A copy of the URL with any instances of ".." or "." removed from its path. (read-only)

Discussion

This property contains a new NSURL object, initialized using the receiver’s path with any instances of ".." or "." removed. If the receiver does not conform to RFC 1808, this property contains nil.

absoluteURL

An absolute URL that refers to the same resource as the receiver. (read-only)

Discussion

If the URL is already absolute, this property contains a copy of the receiver. Resolution is performed per RFC 1808.

URLByStandardizingPath

A URL that points to the same resource as the original URL using an absolute path. (read-only)

Discussion

This property only works on URLs with the file: path scheme. For all other URLs, it returns a copy of the original URL.

Like stringByStandardizingPath, this property can make the following changes in the provided URL:

Expand an initial tilde expression using stringByExpandingTildeInPath.
  Reduce empty components and references to the current directory (that is, the sequences “//” and “/./”) to single path separators.
  In absolute paths only, resolve references to the parent directory (that is, the component “..”) to the real parent directory if possible using stringByResolvingSymlinksInPath, which consults the file system to resolve each potential symbolic link.

In relative paths, because symbolic links can’t be resolved, references to the parent directory are left in place.
  Remove an initial component of “/private” from the path if the result still indicates an existing file or directory (checked by consulting the file system).

Note that the path contained by this property may still have symbolic link components in it. Note also that this property only works with file paths (not, for example, string representations of URLs).

答:
I think the key difference is that two URLs with different absolute paths may actually refer to the same resource, and in that case, they would have the same standardized URL.  Examples of path elements that could cause this are:

```<code>~ vs /absolute/path/to/user/home/directory
paths that include soft links
/path/to/thing vs /path/to/other/../thing
etc.
</code>```

The standardized url (URL.standardizedFileURL in swift) is very useful because two URLs that point to the same file should have the same standardizedFileURL even if they have different absolute paths.  So one should generally use the standardized path if they wish to compare two file URLs.

Body:
I think the key difference is that two URLs with different absolute paths may actually refer to the same resource, and in that case, they would have the same standardized URL.  Examples of path elements that could cause this are:

~ vs /absolute/path/to/user/home/directory
paths that include soft links
/path/to/thing vs /path/to/other/../thing
etc.

The standardized url (URL.standardizedFileURL in swift) is very useful because two URLs that point to the same file should have the same standardizedFileURL even if they have different absolute paths.  So one should generally use the standardized path if they wish to compare two file URLs.