问:
Centre Emacs buffer within window
I wrap all my code at 80 columns, and there are times where the Emacs window is wider than 80 columns and there is a lot of unused whitespace on the right side.

I would like to position the Emacs buffer, so all the text is displayed in the middle of the window.

This is different to centre aligning text (more akin to the whitespace on either side of the text when viewing pdfs).

I think this can be achieved by dynamically adjusting the fringe mode widths, depending on the current window size, but I'm not sure where to start. Any ideas?

答: Modern answer is https://github.com/rnkn/olivetti or https://github.com/joostkremers/writeroom-mode, both worked immediately for me where other things did not</p>

Title: Centre Emacs buffer within window


来源: stackexchange

问:
Named pipes in NSIS
Is there a possiblity to use named pipes from NSIS? If so how can you do it? I could not find anything on the web so I have big doubts this is even possible.</p>

答:
What do you want to use named pipes for?
You can create simple plugin which will perform all tasks you need.</p>

ContentLicense: CC BY-SA 3.0

Title: Named pipes in NSIS


问:
How to run bash command without stalling my terminal
I want to run an app that stalls my terminal but then I need to use that terminal again and can't have it stall, is there some sort of prefix I can apply to a command that will allow it to run asynchronously? Example:</p>
```<code>async mousepad
</code>```

答:
Add & to make the program run in the background.

From the bash manual:

If a command is terminated by the control operator &, the shell executes the command in the background in a subshell. The shell does not wait for the command to finish, and the return       status is 0. These are referred to as asynchronous commands.

ContentLicense: CC BY-SA 4.0

Body:
I want to run an app that stalls my terminal but then I need to use that terminal again and can't have it stall, is there some sort of prefix I can apply to a command that will allow it to run asynchronously? Example:

async mousepad


问:
Matching integers to ranges
I have n integers and m ranges (think [a, b]) of numbers such that n <= m. An integer and a range may be matched if the integer is in the range, i.e., a <= integer <= b. A range may only be matched with one integer and vice versa.

Here is an example:

Ranges: [0, 5], [3, 6], [9, 21]

Integers: 1, 5

The maximum valid matching is to match 1 to the first range and 5 to the second range.

I want to find a greedy algorithm that maximizes the number of integers matched. My initial thought is to greedily choose the shortest range and match the number which is closest to the shortest range's start point (so the a in a range [a, b]). Howveer, I'm not sure this is right.

答:
What if you matched every possible match, allowing multiple connections w.r.t. integers, and eliminated prior matches whenever they participate in multiple connections w.r.t. ranges?  You'd have to follow up by deleting any remaining multiples to obtain a valid result.

In your example, you'd iterate through integers:

```<code>1 : match [0,5]
5 : match [0,5], [3,6] then eliminate [0,5]
</code>```

A little more complex example might be 1, 5, 7 with ranges [0,5], [2,6], [3,10], [5,21]

```<code>1 : match [0,5]
5 : match [0,5], [2,6], [3,10], [5,21] then eliminate [0,5]
7 : match [3,10], [5,21] then eliminate [3,10]
</code>```

You're left with:

```<code>1 : [0,5]
5 : [2,6], [3,10], [5,21]
7 : [5,21]
</code>```

You preferentially eliminate [5,21] from 5 because the range has multiple placements and you're eliminating from an integer with multiple placements.  And finally, you eliminate [3,10] (although your could eliminate [2,6]) to remove all multiples among the integers.

Title: Matching integers to ranges

Body:
What if you matched every possible match, allowing multiple connections w.r.t. integers, and eliminated prior matches whenever they participate in multiple connections w.r.t. ranges?  You'd have to follow up by deleting any remaining multiples to obtain a valid result.

In your example, you'd iterate through integers:

1 : match [0,5]
5 : match [0,5], [3,6] then eliminate [0,5]

A little more complex example might be 1, 5, 7 with ranges [0,5], [2,6], [3,10], [5,21]

1 : match [0,5]
5 : match [0,5], [2,6], [3,10], [5,21] then eliminate [0,5]
7 : match [3,10], [5,21] then eliminate [3,10]

You're left with:

1 : [0,5]
5 : [2,6], [3,10], [5,21]
7 : [5,21]

You preferentially eliminate [5,21] from 5 because the range has multiple placements and you're eliminating from an integer with multiple placements.  And finally, you eliminate [3,10] (although your could eliminate [2,6]) to remove all multiples among the integers.


答:
You need to run it in the background. Haven't tried it with that mousepad command but hopefully this works.

```<code>nohup "COMMAND" &
</code>```

or

```<code>nohup async mousepad &
</code>```

https://linuxize.com/post/how-to-run-linux-commands-in-background/

Title: How to run bash command without stalling my terminal

Body:
You need to run it in the background. Haven't tried it with that mousepad command but hopefully this works.

nohup "COMMAND" &

or

nohup async mousepad &

https://linuxize.com/post/how-to-run-linux-commands-in-background/


问:
Text Comparing Program
I'm making a program where I am supposed to compare text files by returning a list of all the words that come up in the file, and the number of times they come up. I have to disregard a list of words called stopwords so they won't be checked for the number of times they come up. For the first part I need to check if the word is in the stopwords, if it is, i don't count that word, if it isn't in stopwords then I make a brand new row for that word in a dataframe, assuming it doesn't already exist in the data frame, and increment the appearance frequency by 1. Each text file will have a column. I am a little stuck on this part however. I have bits of the code already but I need to fill in the blanks. Here is what I have so far:

```<code>from tkinter.filedialog import askdirectory
import glob

import os
import pandas as pd

def main():
    df = pd.DataFrame(columns =["TEXT FILE NAMES HERE..."])
    data_directory = askdirectory(initialdir = "/School_Files/CISC_121/Assignments/Assignment3/Data_Files")
    stopwords = open(os.getcwd() + "/" + "StopWords.txt")

    text_files = glob.glob(data_directory + "/" + "*.txt")

    for f in text_files:
        infile = open(f, "r", encoding = "UTF-8")
        #now read the file and do all the word-counting etc...
        lines = infile.readlines()
        for line in lines:
            x = 0
            words = line.split()
            while (x < len(words)):
                """
                Check if the word is in the stopwords
                If it isn't, then add the word into a row in a dataframe, for the first occurence, then
                increment the value by 1
                Have a column for each book
                """
                for line in infile:
                    if word in line:
                        found = True
                        word +=1
                    else:
                        found = False

                x = x+1

main()
</code>```

If anyone can help me finish this section I'd really appreciate it. Please show the change in code. Thanks in advance!

答:
I see that you just want to count the occurrence of the words. For this you could use a dictionary instead of a Dataframe.

And for stopwords, read it to a list.

Try the below code.

```<code>stopwords = []
count_dictionary {}

with open(os.getcwd() + "/" + "StopWords.txt") as f:
    stopwords = f.read().splitlines()

#your code

while (x < len(words)):
    if word not in stopwords:
        if word in count_dictionary :
            count_dictionary[word] += 1
        else:
            count_dictionary[word] = 1

</code>```

Title: Text Comparing Program

Body:
I'm making a program where I am supposed to compare text files by returning a list of all the words that come up in the file, and the number of times they come up. I have to disregard a list of words called stopwords so they won't be checked for the number of times they come up. For the first part I need to check if the word is in the stopwords, if it is, i don't count that word, if it isn't in stopwords then I make a brand new row for that word in a dataframe, assuming it doesn't already exist in the data frame, and increment the appearance frequency by 1. Each text file will have a column. I am a little stuck on this part however. I have bits of the code already but I need to fill in the blanks. Here is what I have so far:

from tkinter.filedialog import askdirectory
import glob

import os
import pandas as pd

def main():
    df = pd.DataFrame(columns =["TEXT FILE NAMES HERE..."])
    data_directory = askdirectory(initialdir = "/School_Files/CISC_121/Assignments/Assignment3/Data_Files")
    stopwords = open(os.getcwd() + "/" + "StopWords.txt")

    text_files = glob.glob(data_directory + "/" + "*.txt")

    for f in text_files:
        infile = open(f, "r", encoding = "UTF-8")
        #now read the file and do all the word-counting etc...
        lines = infile.readlines()
        for line in lines:
            x = 0
            words = line.split()
            while (x < len(words)):
                """
                Check if the word is in the stopwords
                If it isn't, then add the word into a row in a dataframe, for the first occurence, then
                increment the value by 1
                Have a column for each book
                """
                for line in infile:
                    if word in line:
                        found = True
                        word +=1
                    else:
                        found = False

                x = x+1

main()

If anyone can help me finish this section I'd really appreciate it. Please show the change in code. Thanks in advance!

Body:
I see that you just want to count the occurrence of the words. For this you could use a dictionary instead of a Dataframe.

And for stopwords, read it to a list.

Try the below code.

stopwords = []
count_dictionary {}

with open(os.getcwd() + "/" + "StopWords.txt") as f:
    stopwords = f.read().splitlines()

#your code

while (x < len(words)):
    if word not in stopwords:
        if word in count_dictionary :
            count_dictionary[word] += 1
        else:
            count_dictionary[word] = 1


问:
How can I write a where clause in SQL to filter a DATETIME column by the time of day?
I have data that is timestamped with a DATETIME column and I want to filter it down to the set of records where the DATETIME is between 9:30am and 5:30pm for any day.  What's the best way to do this?

UPDATE: Changed because I need precision to the minute, not just hour.  Sorry about that.

答:
```<code>SELECT
     *
FROM
     My_Table
WHERE
     DATEPART(hh, some_date) BETWEEN 9 AND 16 OR
     (DATEPART(hh, some_date) = 17 AND DATEPART(mm, some_date) = 0...)
</code>```

Alternatively:

```<code>SELECT
     *
FROM
     My_Table
WHERE
     DATEADD(dd, 1-DATEPART(dd, some_date),
          DATEADD(mm, 1-DATEPART(mm, some_date),
               DATEADD(yy, 1900-DATEPART(yy, some_date), some_date)))
     BETWEEN @start_time AND @end_time
</code>```

Just make your @start_time and @end_time 1900-01-01 with the time needed.

That will exclude 05:00:00.000 PM, but you should be able to adjust if needed. Also keep in mind that it can't efficiently use indexes for this search. If the time of day is often going to be used for searching or calculations you might consider separating it out and keeping DATE and TIME as two columns.

OwnerDisplayName: Bialecki

ContentLicense: CC BY-SA 2.5

LastEditorDisplayName: Milen A. Radev

Body:
SELECT
     *
FROM
     My_Table
WHERE
     DATEPART(hh, some_date) BETWEEN 9 AND 16 OR
     (DATEPART(hh, some_date) = 17 AND DATEPART(mm, some_date) = 0...)

Alternatively:

SELECT
     *
FROM
     My_Table
WHERE
     DATEADD(dd, 1-DATEPART(dd, some_date),
          DATEADD(mm, 1-DATEPART(mm, some_date),
               DATEADD(yy, 1900-DATEPART(yy, some_date), some_date)))
     BETWEEN @start_time AND @end_time

Just make your @start_time and @end_time 1900-01-01 with the time needed.

That will exclude 05:00:00.000 PM, but you should be able to adjust if needed. Also keep in mind that it can't efficiently use indexes for this search. If the time of day is often going to be used for searching or calculations you might consider separating it out and keeping DATE and TIME as two columns.

OwnerDisplayName: Tom H.

LastEditorDisplayName: Tom H.


问:
get certain property from app.config without looping
i need your help

i have app.config like this

```<code><?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    ...
  </configSections>
  <connectionStrings>
    ...
  </connectionStrings>
  <appSettings />
  <userSettings>
    <MySettings>
      <setting name="Precision" serializeAs="String">
        <value>0</value>
      </setting>
    </MySettings>
  </userSettings>
  <applicationSettings>
    ...
  </applicationSettings>
</configuration>
</code>```

what I need is to get 'Precision' value. how to get that without looping SectionGroups, SectionCollection?

note:
I've DAL and in my DAL need this precision to format the decimal value and the precision is managed by user(client) through the Presentation Layer. I save the precision value in app.config. The problem, the app.config is in Presentiation Layer, and I cannot use Properties.MySetting.Default.Precision to get that. (Thanks to Branko & Tim to remind me about this reason)

答:
I would consider "settings injection" here - like dependency injection, but for settings :)

Presumably your entry point configures the whole system... so get it to read all the settings from app.config, and use those when creating and configuring the DAL (and anywhere else which needs settings). The only piece of code which needs to know how to use app.config can be the entry point. Everything else can be specified via POCOs, individual constructor parameters etc.

This is good in several ways:

Your code will be easier to test: to test different settings, just pass in different constructor arguments. No need for files etc.

Your immediate problem is solved: the DAL no longer needs to look through the settings file

You're isolating your configuration storage in a single place which can change if you decide to (say) use a different XML format, or an "ini"-style configuration format

Body:
i need your help

i have app.config like this

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    ...
  </configSections>
  <connectionStrings>
    ...
  </connectionStrings>
  <appSettings />
  <userSettings>
    <MySettings>
      <setting name="Precision" serializeAs="String">
        <value>0</value>
      </setting>
    </MySettings>
  </userSettings>
  <applicationSettings>
    ...
  </applicationSettings>
</configuration>

what I need is to get 'Precision' value. how to get that without looping SectionGroups, SectionCollection?

note:
I've DAL and in my DAL need this precision to format the decimal value and the precision is managed by user(client) through the Presentation Layer. I save the precision value in app.config. The problem, the app.config is in Presentiation Layer, and I cannot use Properties.MySetting.Default.Precision to get that. (Thanks to Branko & Tim to remind me about this reason)


问:
How to create an object of a custom class in Window PowerShell console?
I have created a simple class using Windows PowerShell ISE. The class definition is as follows.

```<code>class Person {
 [string] $FirstName
 [string] $LastName

    Person() {
    }

    [string] Greeting() {
        return "Greetings, {0} {1}!" -f $this.FirstName, $this.LastName
    }
}
</code>```

Now from within PowerShell console when I attempt to create an object from this class like this:

```<code>$x = [Person]::new()
</code>```

It says

Unable to find type [Person].

答:
Your class definition is perfectly valid. The easiest way of starting to use your class is adding code in the same file below:

```<code>class Person {
 [string] $FirstName
 [string] $LastName

    Person() {
    }

    [string] Greeting() {
        return "Greetings, {0} {1}!" -f $this.FirstName, $this.LastName
    }
}

# Using constructor
$x = [Person]::new()

# Setting up properties
$x.FirstName = "Alex"
$x.LastName = "K"

# Running a method
$x.Greeting()
</code>```

Greetings, Alex K!

Body:
I have created a simple class using Windows PowerShell ISE. The class definition is as follows.

class Person {
 [string] $FirstName
 [string] $LastName

    Person() {
    }

    [string] Greeting() {
        return "Greetings, {0} {1}!" -f $this.FirstName, $this.LastName
    }
}

Now from within PowerShell console when I attempt to create an object from this class like this:

$x = [Person]::new()

It says

Unable to find type [Person].

Body:
Your class definition is perfectly valid. The easiest way of starting to use your class is adding code in the same file below:

class Person {
 [string] $FirstName
 [string] $LastName

    Person() {
    }

    [string] Greeting() {
        return "Greetings, {0} {1}!" -f $this.FirstName, $this.LastName
    }
}

# Using constructor
$x = [Person]::new()

# Setting up properties
$x.FirstName = "Alex"
$x.LastName = "K"

# Running a method
$x.Greeting()

Greetings, Alex K!


问:
How do I disconnect a user from a discord channel with discord js?
The main issue seems to be that things are undefined. For example, a very simple version of something I have tried:

```<code>else if (message.content.startsWith("!dc")) {
    message.author.voice.setChannel(null);
}
</code>```

Resulting in the terminal returning:

TypeError: Cannot read properties of undefined (reading 'setChannel')

I'm not quite sure how to "define" these as some solutions I've found online seem to do what I am trying to do in a similar way. Am I just missing something obvious?

I also have these Intents declared at the top.

```<code>const client = new Discord.Client({
intents: [
    Discord.Intents.FLAGS.GUILDS,
    Discord.Intents.FLAGS.GUILD_MESSAGES,
    Discord.Intents.FLAGS.GUILD_VOICE_STATES,
    Discord.Intents.FLAGS.GUILD_MEMBERS
    ]
});
</code>```

答:
I don't think you can disconnect yourself while you are admin.
So try this

return <member>.voice.setChannel(null)
    .then(() => message.channel.send(`Done`))
    .catch((err) => message.channel.send(`\\❌ | ${err}!`));
```

Body:
The main issue seems to be that things are undefined. For example, a very simple version of something I have tried:

else if (message.content.startsWith("!dc")) {
    message.author.voice.setChannel(null);
}

Resulting in the terminal returning:

TypeError: Cannot read properties of undefined (reading 'setChannel')

I'm not quite sure how to "define" these as some solutions I've found online seem to do what I am trying to do in a similar way. Am I just missing something obvious?

I also have these Intents declared at the top.

const client = new Discord.Client({
intents: [
    Discord.Intents.FLAGS.GUILDS,
    Discord.Intents.FLAGS.GUILD_MESSAGES,
    Discord.Intents.FLAGS.GUILD_VOICE_STATES,
    Discord.Intents.FLAGS.GUILD_MEMBERS
    ]
});


问:
Reponse Data with Selenium driver
The code below currently opens page and logins into site. URL is a private company link I can not post.

```<code>import pandas as pd
import requests
from bs4 import BeautifulSoup
from selenium import webdriver

driver = webdriver.Edge()
url = 'SomeURL'

def login(url):
    driver.get(url)
    print('1')
    driver.find_element_by_css_selector("input[type=text]").send_keys("Username")
    print('2')
    driver.find_element_by_css_selector("input[type=password]").send_keys("password")
    print('3')
    driver.find_element_by_css_selector("button[type=submit]").click()
    print('4') #####Here is where I am having issues#####
    json = driver.find_element_by_tag_name("pre")
    print(json)
    return(json)

data = login(url)
</code>```

The function is missing a critical part of what I need. Once I have logged in I need to return the text inside pre html tag form the new page.

My print statement returns this

```<code><selenium.webdriver.remote.webelement.WebElement (session="79adcfff4b079a895939502f55ce2fc9", element="29fb8a33-a986-40cb-9b1b-2041096f6240")>
</code>```

How do I return the text inside pre tag once I have logged into site that what I need. Thanks

答:
After print 4 these are the commands to run in order to get page source from new login in page and return the html back to caller.</p>
```<code>newURI = driver.window_handles[0]
driver.switch_to.window(newURI)
time.sleep(3)
print('5')
pageSource = driver.page_source.encode('utf-8')
print('6')
return(pageSource)
</code>```

Title: Reponse Data with Selenium driver

Body:
The code below currently opens page and logins into site. URL is a private company link I can not post.

import pandas as pd
import requests
from bs4 import BeautifulSoup
from selenium import webdriver

driver = webdriver.Edge()
url = 'SomeURL'

def login(url):
    driver.get(url)
    print('1')
    driver.find_element_by_css_selector("input[type=text]").send_keys("Username")
    print('2')
    driver.find_element_by_css_selector("input[type=password]").send_keys("password")
    print('3')
    driver.find_element_by_css_selector("button[type=submit]").click()
    print('4') #####Here is where I am having issues#####
    json = driver.find_element_by_tag_name("pre")
    print(json)
    return(json)

data = login(url)

The function is missing a critical part of what I need. Once I have logged in I need to return the text inside pre html tag form the new page.

My print statement returns this

<selenium.webdriver.remote.webelement.WebElement (session="79adcfff4b079a895939502f55ce2fc9", element="29fb8a33-a986-40cb-9b1b-2041096f6240")>

How do I return the text inside pre tag once I have logged into site that what I need. Thanks

Body:
After print 4 these are the commands to run in order to get page source from new login in page and return the html back to caller.

newURI = driver.window_handles[0]
driver.switch_to.window(newURI)
time.sleep(3)
print('5')
pageSource = driver.page_source.encode('utf-8')
print('6')
return(pageSource)


问:
Stripe preview discounted price before applying subscription update
I am working on a Stripe project and there are basically two things I need to achieve and failed to find in the documentation how so far:

Our app needs to allow applying promotion codes (coupons) to already existing Subscriptions, I need to

check whether given promotion code is applicable for the given subscription before actually updating the subscription (some promo codes may be limited to "first-time order only", or limited by minimum order value)

show/preview the discounted price the user would get if they applied this coupon

The user sees their subscription, they can input promo code & try to apply it, get the discounted price they would get with this promo code and THEN they can choose to submit/update the subscription.

Is it possible to do something like this with Stripe API?

I have tried:

manually retrieving the promo codes and check their .active property, but that doesn't take into account specific restrictions like first-time order or minimum order value

with creating new subscriptions through Checkout Session it's easy, I can try to retrieve the session URL and if the promo code cannot be applied, I receive and handle the error, but the problem is with updating already existing subscriptions, it would be nice if there were some equivalent of the "try to get checkout session with applied coupon" option

I could try my best to guess if the promo code would be applicable by retrieving all the information about the promo code (.restrictions prop) and the subscription and manually compare everything and then manually calculate how the price would look like, but it looks over-complicated, prone to errors and I would be much more confident if I could just input the subscription and the promo code, tried to "pre-apply" it and Stripe told me OK/not OK

Any ideas? Is there any "try to apply coupon"/"check if applicable"/"preview discount" feature?

I have the feeling I can hardly be the first one with this required functionality, and everyone can't solve it just by applying the promo code "blindly", right?

答:
Yes, you can do this by providing the coupon to the Upcoming Invoice endpoint.

https://stripe.com/docs/api/invoices/upcoming#upcoming_invoice-coupon

You specify the subscription and may want to disable proration with subscription_proration_behavior=none for the current period (up to you).


问:
Add thousand separator with javascript when add input dynamically
I have problem when adding input dynamically with thousand separator,
when I click add and the input form appears.
it should be when I type the number it will be arranged in thousand separator.
Please help me

$(document).ready(function(){
 $(document).on('click', '.add', function(){
  var html = '';
  html += '
';
  html += '<input type="text" name="item_name[]" class="form-control inputnumber" onkeypress="return event.keyCode > 47 && event.keyCode < 58 || event.keyCode == 46" />	';
  html += '
';
  $('#item_table').append(html);
 });

$('input.inputnumber').keyup(function(event) {
  if (event.which >= 37 && event.which <= 40) return;
  $(this).val(function(index, value) {
    return value
      // Keep only digits and decimal points:
      .replace(/[^\d.]/g, "")
      // Remove duplicated decimal point, if one exists:
      .replace(/^(\d*\.)(.*)\.(.*)$/, '$1$2$3')
      // Keep only two digits past the decimal point:
      .replace(/\.(\d{2})\d+/, '.$1')
      // Add thousands separators:
      .replace(/\B(?=(\d{3})+(?!\d))/g, ",")
  });
});
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <div class="table-repsonsive">
     <table class="table table-bordered" id="item_table">
      <tr>
       <th><button type="button" name="add" class="btn btn-success btn-sm add">ADD</button></th>
      </tr>
     </table>
    </div></code>```

答:
You can use the NumberFormat object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat

$(document).ready(function() {
  $(document).on('click', '.add', function() {
    var html = '';
    html += '
';
    html += '<input type="text" name="item_name[]" class="form-control inputnumber" >	';
    html += '
';
    $('#item_table').append(html);
  });

  $('#item_table').change(function(event) {
    if (event.target.classList.contains("inputnumber")) {
      // remove any commas from earlier formatting
      const value = event.target.value.replace(/,/g, '');
      // try to convert to an integer
      const parsed = parseInt(value);
      // check if the integer conversion worked and matches the expected value
      if (!isNaN(parsed) && parsed == value) {
        // update the value
        event.target.value = new Intl.NumberFormat('en-US').format(value);
      }
    }
  });
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="table-repsonsive">
  <table class="table table-bordered" id="item_table">
    <tr>
      <th><button type="button" name="add" class="btn btn-success btn-sm add">ADD</button></th>
    </tr>
  </table>
</div></code>```

Body:
I have problem when adding input dynamically with thousand separator,
when I click add and the input form appears.
it should be when I type the number it will be arranged in thousand separator.
Please help me

$(document).ready(function(){
 $(document).on('click', '.add', function(){
  var html = '';
  html += '
';
  html += '<input type="text" name="item_name[]" class="form-control inputnumber" onkeypress="return event.keyCode > 47 && event.keyCode < 58 || event.keyCode == 46" />	';
  html += '
';
  $('#item_table').append(html);
 });

$('input.inputnumber').keyup(function(event) {
  if (event.which >= 37 && event.which <= 40) return;
  $(this).val(function(index, value) {
    return value
      // Keep only digits and decimal points:
      .replace(/[^\d.]/g, "")
      // Remove duplicated decimal point, if one exists:
      .replace(/^(\d*\.)(.*)\.(.*)$/, '$1$2$3')
      // Keep only two digits past the decimal point:
      .replace(/\.(\d{2})\d+/, '.$1')
      // Add thousands separators:
      .replace(/\B(?=(\d{3})+(?!\d))/g, ",")
  });
});
});

       <button type="button" name="add" class="btn btn-success btn-sm add">ADD</button>

Body:
You can use the NumberFormat object

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat

$(document).ready(function() {
  $(document).on('click', '.add', function() {
    var html = '';
    html += '<tr>';
    html += '<td><input type="text" name="item_name[]" class="form-control inputnumber" ></td>';
    html += '</tr>';
    $('#item_table').append(html);
  });

  $('#item_table').change(function(event) {
    if (event.target.classList.contains("inputnumber")) {
      // remove any commas from earlier formatting
      const value = event.target.value.replace(/,/g, '');
      // try to convert to an integer
      const parsed = parseInt(value);
      // check if the integer conversion worked and matches the expected value
      if (!isNaN(parsed) && parsed == value) {
        // update the value
        event.target.value = new Intl.NumberFormat('en-US').format(value);
      }
    }
  });
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="table-repsonsive">
  <table class="table table-bordered" id="item_table">
    <tr>
      <th><button type="button" name="add" class="btn btn-success btn-sm add">ADD</button></th>
    </tr>
  </table>
</div>


问:
How to replace body text in MIME message?
I am trying to send an automated email to various users with the lake that they are subscribed to changing:

message = MIMEMultipart()
message['From'] = email  # Sender
message['Subject'] = "Algae Bloom Alert\n"  # Subject

for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']
    message['To'] = subscriber_dict[user]['email']
    body = (
        f"This is an algae alert for Lake {subscriber_dict[user]['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))  # Attaching body to email
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)

    # Reset body here ideally

    print(f"Email sent at {formatted_time}")
```

However, when the emails are sent, each successive email contains the contents from the emails prior to it. Does anyone know how I can reset the body so that I am not attaching to the previous bodies but rather writing new ones?

答:
Righto - there's no need to keep digging back into subscriber_dict. Instead of:

for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']
```
<p>You can do:</p>
<pre class="lang-py prettyprint-override"><code>for user in subscriber_dict.values():
    sms_gateway = user['email']
</code>```

Your for loop is reusing the same message. It should probably create a new one on each loop:

FROM_ADDR = "jake@lakefacts.gov.au"

for user in subscriber_dict.values():
    message = MIMEMultipart()
    message['From'] = FROM_ADDR
    message['To'] = user['email']
    message['Subject'] = "Algae Bloom Alert\n"
    body = (
        f"This is an algae alert for Lake {user['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))
    sms_gateway = user['email']
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)
    print(f"Email sent at {formatted_time}")
```

Body:
I am trying to send an automated email to various users with the lake that they are subscribed to changing:

message = MIMEMultipart()
message['From'] = email  # Sender
message['Subject'] = "Algae Bloom Alert\n"  # Subject

for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']
    message['To'] = subscriber_dict[user]['email']
    body = (
        f"This is an algae alert for Lake {subscriber_dict[user]['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))  # Attaching body to email
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)

    # Reset body here ideally

    print(f"Email sent at {formatted_time}")

However, when the emails are sent, each successive email contains the contents from the emails prior to it. Does anyone know how I can reset the body so that I am not attaching to the previous bodies but rather writing new ones?

Body:
Righto - there's no need to keep digging back into subscriber_dict. Instead of:

for user in subscriber_dict:
    sms_gateway = subscriber_dict[user]['email']

You can do:

for user in subscriber_dict.values():
    sms_gateway = user['email']

Your for loop is reusing the same message. It should probably create a new one on each loop:

FROM_ADDR = "jake@lakefacts.gov.au"

for user in subscriber_dict.values():
    message = MIMEMultipart()
    message['From'] = FROM_ADDR
    message['To'] = user['email']
    message['Subject'] = "Algae Bloom Alert\n"
    body = (
        f"This is an algae alert for Lake {user['lake']}.\n\n"
        f"Sent at {sent_time_date} {sent_time_time}"
    )
    message.attach(MIMEText(body, 'plain'))
    sms_gateway = user['email']
    sms = message.as_string()
    server.sendmail(email, sms_gateway, sms)
    print(f"Email sent at {formatted_time}")


问:
How to subset R data frame based on duplicates in one column and unique values in another
This seems pretty straightforward but I am stumped. I have a data frame that looks like this:

```<code>df1 %>% head()
  values  paired
  <ch>     <int>
1 apples      1
2 x           1
3 oranges     2
4 z           2
5 bananas     3
6 y           3
7 apples      4
8 p           4

</code>```

I would like to create a new data frame that extracts all paired values based on a search criteria. So if I want all pairs that correspond to apples I would like to end up with something like this:

```<code>df1 %>% head()
  values  paired
  <ch>     <int>
1 apples      1
2 x           1
3 apples      4
4 p           4
</code>```

I have tried using:

```<code>new_pairs <- df1 %>%
  arrange(values, paired) %>%
  filter(duplicated(paired) == TRUE,
         values=="apples")
</code>```

But I am getting only the apple rows back

答:
You'll need to group on the paired variable before filtering.

How about:

```<code>df1 %>%
  group_by(paired) %>%
  filter("apples" %in% values) %>%
  ungroup()
</code>```

Result:

```<code># A tibble: 4 x 2
  values paired
  <chr>   <int>
1 apples      1
2 x           1
3 apples      4
4 p           4
</code>```

Your data:

```<code>df1 <- structure(list(values = c("apples", "x", "oranges", "z", "bananas", "y", "apples", "p"),
                      paired = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L)),
                 class = "data.frame",
                 row.names = c("1", "2", "3", "4", "5", "6", "7", "8"))
</code>```

Body:
This seems pretty straightforward but I am stumped. I have a data frame that looks like this:

df1 %>% head()
  values  paired
  <ch>     <int>
1 apples      1
2 x           1
3 oranges     2
4 z           2
5 bananas     3
6 y           3
7 apples      4
8 p           4

I would like to create a new data frame that extracts all paired values based on a search criteria. So if I want all pairs that correspond to apples I would like to end up with something like this:

df1 %>% head()
  values  paired
  <ch>     <int>
1 apples      1
2 x           1
3 apples      4
4 p           4

I have tried using:

new_pairs <- df1 %>%
  arrange(values, paired) %>%
  filter(duplicated(paired) == TRUE,
         values=="apples")

But I am getting only the apple rows back

Body:
You'll need to group on the paired variable before filtering.

How about:

df1 %>%
  group_by(paired) %>%
  filter("apples" %in% values) %>%
  ungroup()

Result:

# A tibble: 4 x 2
  values paired
  <chr>   <int>
1 apples      1
2 x           1
3 apples      4
4 p           4

Your data:

df1 <- structure(list(values = c("apples", "x", "oranges", "z", "bananas", "y", "apples", "p"),
                      paired = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L)),
                 class = "data.frame",
                 row.names = c("1", "2", "3", "4", "5", "6", "7", "8"))


问:
Viewing MBeans through jstatd
I am trying to monitor all Java processes running on a server via jstatd.  I've got it set up enough that I can connect with VisualVM and see all running processes.  Most displays work fine, however certain things (especially CPU usage and MBeans) do not display.  Instead, it says:

MBeans Browser

Data not available because JMX connection to the JMX agent could not be established.

I assumed that the problem was that the application must "announce" through the jstatd RMI registry rather than a local one, so I tried out the following (per these suggestions) but it still won't display.  The code I tried is as follows:

```<code>public class JmxRmiConnectorTest {
    public static void main(String[] args) throws Exception {
        Registry rmiRegistry = LocateRegistry.createRegistry(9994);
        String svc =
            "service:jmx:rmi://localhost:9994/jndi/rmi://localhost:1099/connector";

        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();

        JMXServiceURL url = new JMXServiceURL(svc);
        RMIConnectorServer rmiServer = new RMIConnectorServer(url, null, mbeanServer);
        rmiServer.start();

        Thread.sleep(100000);

        rmiServer.stop();
    }
}
</code>```

How can I get my MBeans and CPU usage to show up in VisualVM when seen through jstatd?

答:
Just for those who need a quick working method.
JMX can be start/stop dynamically, that's without restart of JVM.
In my case, after start jmx dynamically and restart jvisualvm, JMX and cpu usage works fine.

```<code>jcmd PID ManagementAgent.start jmxremote.port=9999 jmxremote.ssl=false jmxremote.authenticate=false
</code>```

or

```<code>jcmd PID ManagementAgent.stop
</code>```

Title: Viewing MBeans through jstatd

Body:
I am trying to monitor all Java processes running on a server via jstatd.  I've got it set up enough that I can connect with VisualVM and see all running processes.  Most displays work fine, however certain things (especially CPU usage and MBeans) do not display.  Instead, it says:

MBeans Browser

Data not available because JMX connection to the JMX agent could not be established.

I assumed that the problem was that the application must "announce" through the jstatd RMI registry rather than a local one, so I tried out the following (per these suggestions) but it still won't display.  The code I tried is as follows:

public class JmxRmiConnectorTest {
    public static void main(String[] args) throws Exception {
        Registry rmiRegistry = LocateRegistry.createRegistry(9994);
        String svc =
            "service:jmx:rmi://localhost:9994/jndi/rmi://localhost:1099/connector";

        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();

        JMXServiceURL url = new JMXServiceURL(svc);
        RMIConnectorServer rmiServer = new RMIConnectorServer(url, null, mbeanServer);
        rmiServer.start();

        Thread.sleep(100000);

        rmiServer.stop();
    }
}

How can I get my MBeans and CPU usage to show up in VisualVM when seen through jstatd?

Body:
Just for those who need a quick working method.
JMX can be start/stop dynamically, that's without restart of JVM.
In my case, after start jmx dynamically and restart jvisualvm, JMX and cpu usage works fine.

jcmd PID ManagementAgent.start jmxremote.port=9999 jmxremote.ssl=false jmxremote.authenticate=false

or

jcmd PID ManagementAgent.stop


问:
Unable to mock a dependent function if its from the same module
I have been trying to debug why this is happening. I am unable to mock a dependent function if its from the same module as the function calling it. But I am able to overcome this if the mocked function is moved to a separate module which is different from the module of the function calling it.

Not working scenario

Module A (filename.ts)

export const callingFunction = () => {
  //....statements
  dependentFunction();
}

export const dependantFunction = () => {
  //....statements
  //resolve with something
}```
</div>
</div>
</p>
<p><strong>filename.test.ts</strong></p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>import { callingFunction } from './fileName'

jest.mock('./fileName',() =>  ({
 ...jest.requireActuals('./fileName'),
 dependentFunction: jest.fn().mockImplementation(/*....Mocked implementation*/)
})

test('...test case description...', () => {
  const callingFunctionRespose: any = callingFunction();
  expect(callingFunctionResponse).toEqual(/*....something.....*/);
});</code>```

The above mock does not override the dependentFunction exported by the fileName.ts module. Instead, when the exported function callingFunction() is called, it uses the implementation defined in the module. (Found this out by logging the function definitions.

But this behaviour is not observed when the dependant function is moved to it own separate module.

Working scenario

fileName.ts

import { dependentFunction } from './dependentFunctions'

export const callingFunction = () => {
  //....statements
  dependentFunction();
}```
</div>
</div>
</p>
<p><strong>dependentFunctions.ts</strong></p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>export const dependantFunction = () => {
  //....statements
  //resolve with something
}</code>```

fileName.test.ts

import { callingFunction } from './fileName'

jest.mock('./dependentFunctions',() =>  ({
 ...jest.requireActuals('./dependentFunctions'),
 dependentFunction: jest.fn().mockImplementation(/*....Mocked implementation*/)
})

test('...test case description...', () => {
  const callingFunctionRespose: any = callingFunction();
  expect(callingFunctionResponse).toEqual(/*....something.....*/);
});```

答:
You can import the functions as a module

import * as module from './fileName'

To mock the implementation you can do

jest.spyOn(module, 'dependentFunction').mockImplementation(/*....Mocked implementation*/)

To call the other function,  use
module.callingFunction()

Body:
I have been trying to debug why this is happening. I am unable to mock a dependent function if its from the same module as the function calling it. But I am able to overcome this if the mocked function is moved to a separate module which is different from the module of the function calling it.

Not working scenario

Module A (filename.ts)

export const callingFunction = () => {
  //....statements
  dependentFunction();
}

export const dependantFunction = () => {
  //....statements
  //resolve with something
}

filename.test.ts

import { callingFunction } from './fileName'

jest.mock('./fileName',() =>  ({
 ...jest.requireActuals('./fileName'),
 dependentFunction: jest.fn().mockImplementation(/*....Mocked implementation*/)
})

test('...test case description...', () => {
  const callingFunctionRespose: any = callingFunction();
  expect(callingFunctionResponse).toEqual(/*....something.....*/);
});

The above mock does not override the dependentFunction exported by the fileName.ts module. Instead, when the exported function callingFunction() is called, it uses the implementation defined in the module. (Found this out by logging the function definitions.

But this behaviour is not observed when the dependant function is moved to it own separate module.

Working scenario

fileName.ts

import { dependentFunction } from './dependentFunctions'

export const callingFunction = () => {
  //....statements
  dependentFunction();
}

dependentFunctions.ts

export const dependantFunction = () => {
  //....statements
  //resolve with something
}

fileName.test.ts

import { callingFunction } from './fileName'

jest.mock('./dependentFunctions',() =>  ({
 ...jest.requireActuals('./dependentFunctions'),
 dependentFunction: jest.fn().mockImplementation(/*....Mocked implementation*/)
})

test('...test case description...', () => {
  const callingFunctionRespose: any = callingFunction();
  expect(callingFunctionResponse).toEqual(/*....something.....*/);
});


问:
Removing multiple headers in a single excel sheet
Similar to Remove header row in Excel using pandas

I wish to remove headers from an excel sheet.

Using the same example but edited:

```<code>Company ABC

Account Name 1
Account No.1
Description    group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals                               sum values

Account Name 2
Account No.2
Description    group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals                               sum values

Sales
00234
Description    group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals                               sum values

Inventory
00012345
Description    group     pair          amount    ...  result
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9
totals                               sum values
</code>```

I wish to concatenate it to become like

```<code>cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9
</code>```

I've managed to remove the top header by skipping rows e.g.(skiprows = 4). However, This still leaves the other headers and totals which append like so:

```<code>cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals                               sum values
Account Name 2
Account No.2
cabinet_name   group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals                               sum values
Sales
00234
Description    group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals                               sum values
Inventory
00012345
Description    group     pair          amount    ...  result
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9
totals                               sum values
</code>```

Would be extremely grateful if someone could enlighten me on how to clean this sheet with pandas as all I've seen online are working on only 1 table in a single excel sheet.

Let me know if I've missed anything out, I would gladly edit this question.

I thought this might be useful,

My usual process for cleaning the files in excel, is to firstly delete the first 4 rows, only leaving

```<code>cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals         *blank*   *blank*       sum values

Account Name 2
Account No.2
cabinet_name   group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals         *blank*   *blank*       sum values

Account Name 3
Account No.3
cabinet_name   group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals         *blank*   *blank*       sum values
</code>```

Then I will filter group or pair to look for blank values in said column and deleting it.

This is the result of

```<code>print(df_total.head(8).to_dict())
</code>```
```<code>import datetime
from numpy import nan
{'Date': {0: nan, 1: datetime.datetime(2021, 1, 1, 0, 0), 2: datetime.datetime(2021, 1, 1, 0, 0), 3: datetime.datetime(2021, 1, 29, 0, 0), 4: datetime.datetime(2021, 1, 31, 0, 0), 5:
'Totals', 6: 'Net difference', 7: nan},
'Journal number': {0: nan, 1: 'AX009473', 2: 'AX009473', 3: 'AX003312', 4: 'AX009641', 5: nan, 6: nan, 7: nan},
'Voucher': {0: nan, 1: 'TSPN-2021-3', 2: 'TSPN-2021-3', 3: 'GBJ-2021-1', 4: 'VIT-2021-1', 5: nan, 6: nan, 7: nan},
'Posting type': {0: nan, 1: nan, 2: nan, 3: 'Ledger journal', 4: 'Ledger journal', 5: nan, 6: nan, 7: nan},
'Ledger account': {0: nan, 1: '00388211', 2: '00388211', 3: '00388211', 4: '00388211', 5: nan, 6: nan, 7: nan},
'Description': {0: nan, 1: nan, 2: nan, 3: 'DISBERSMENT FOR PETROL', 4: 'TAXI FAIR', 5: nan, 6: nan, 7: nan},
'Unnamed: 6': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan},
'Unnamed: 7': {0: nan, 1: 'SGD', 2: 'USD', 3: 'SGD', 4: 'SGD', 5: nan, 6: nan, 7: nan},
'Amount in transaction currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: nan, 6: nan, 7: nan}, 'Unnamed: 9': {0: 'Credit', 1: 0, 2: 25, 3: 52, 4: 0, 5: nan, 6: nan, 7: nan},
'Amount in accounting currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: 18.55, 6: nan, 7: nan}, 'Unnamed: 11': {0: 'Credit', 1: 0, 2: 33.42, 3: 52, 4: 0, 5: 85.42, 6: 66.87, 7: nan},
'Amount in reporting currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: 18.55, 6: nan, 7: nan}, 'Unnamed: 13': {0: 'Credit', 1: 0, 2: 33.42, 3: 52, 4: 0, 5: 85.42, 6: nan, 7: nan},
'Unnamed: 14': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}, 'Unnamed: 15': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}, 'Unnamed: 16': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}}
</code>```

Created a specimen excel of what I have

VS

An excel of transformed data

答:
You could try to remove the unwanted rows like this.</p>
```<code>df= df[~df['first_column_name'].str.startswith(('Company name','Account Name','Account No.','cabinet_name'))]
</code>```

Body:
Similar to Remove header row in Excel using pandas

I wish to remove headers from an excel sheet.

Using the same example but edited:

Company ABC

Account Name 1
Account No.1
Description    group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals                               sum values

Account Name 2
Account No.2
Description    group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals                               sum values

Sales
00234
Description    group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals                               sum values

Inventory
00012345
Description    group     pair          amount    ...  result
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9
totals                               sum values

I wish to concatenate it to become like

cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9

I've managed to remove the top header by skipping rows e.g.(skiprows = 4). However, This still leaves the other headers and totals which append like so:

cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals                               sum values
Account Name 2
Account No.2
cabinet_name   group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals                               sum values
Sales
00234
Description    group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals                               sum values
Inventory
00012345
Description    group     pair          amount    ...  result
value7         value7    value7        value7    ...  value7
value8         value8    value8        value8    ...  value8
value9         value9    value9        value9    ...  value9
totals                               sum values

Would be extremely grateful if someone could enlighten me on how to clean this sheet with pandas as all I've seen online are working on only 1 table in a single excel sheet.

Let me know if I've missed anything out, I would gladly edit this question.

I thought this might be useful,

My usual process for cleaning the files in excel, is to firstly delete the first 4 rows, only leaving

cabinet_name   group     pair          amount    ...  result
value1         value1    value1        value1    ...  value1
value2         value2    value2        value2    ...  value2
totals         *blank*   *blank*       sum values

Account Name 2
Account No.2
cabinet_name   group     pair          amount    ...  result
value3         value3    value3        value3    ...  value3
value4         value4    value4        value4    ...  value4
totals         *blank*   *blank*       sum values

Account Name 3
Account No.3
cabinet_name   group     pair          amount    ...  result
value5         value5    value5        value5    ...  value5
value6         value6    value6        value6    ...  value6
totals         *blank*   *blank*       sum values

Then I will filter group or pair to look for blank values in said column and deleting it.

This is the result of

print(df_total.head(8).to_dict())

import datetime
from numpy import nan
{'Date': {0: nan, 1: datetime.datetime(2021, 1, 1, 0, 0), 2: datetime.datetime(2021, 1, 1, 0, 0), 3: datetime.datetime(2021, 1, 29, 0, 0), 4: datetime.datetime(2021, 1, 31, 0, 0), 5:
'Totals', 6: 'Net difference', 7: nan},
'Journal number': {0: nan, 1: 'AX009473', 2: 'AX009473', 3: 'AX003312', 4: 'AX009641', 5: nan, 6: nan, 7: nan},
'Voucher': {0: nan, 1: 'TSPN-2021-3', 2: 'TSPN-2021-3', 3: 'GBJ-2021-1', 4: 'VIT-2021-1', 5: nan, 6: nan, 7: nan},
'Posting type': {0: nan, 1: nan, 2: nan, 3: 'Ledger journal', 4: 'Ledger journal', 5: nan, 6: nan, 7: nan},
'Ledger account': {0: nan, 1: '00388211', 2: '00388211', 3: '00388211', 4: '00388211', 5: nan, 6: nan, 7: nan},
'Description': {0: nan, 1: nan, 2: nan, 3: 'DISBERSMENT FOR PETROL', 4: 'TAXI FAIR', 5: nan, 6: nan, 7: nan},
'Unnamed: 6': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan},
'Unnamed: 7': {0: nan, 1: 'SGD', 2: 'USD', 3: 'SGD', 4: 'SGD', 5: nan, 6: nan, 7: nan},
'Amount in transaction currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: nan, 6: nan, 7: nan}, 'Unnamed: 9': {0: 'Credit', 1: 0, 2: 25, 3: 52, 4: 0, 5: nan, 6: nan, 7: nan},
'Amount in accounting currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: 18.55, 6: nan, 7: nan}, 'Unnamed: 11': {0: 'Credit', 1: 0, 2: 33.42, 3: 52, 4: 0, 5: 85.42, 6: 66.87, 7: nan},
'Amount in reporting currency': {0: 'Debit', 1: 13.55, 2: 0, 3: 0, 4: 5, 5: 18.55, 6: nan, 7: nan}, 'Unnamed: 13': {0: 'Credit', 1: 0, 2: 33.42, 3: 52, 4: 0, 5: 85.42, 6: nan, 7: nan},
'Unnamed: 14': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}, 'Unnamed: 15': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}, 'Unnamed: 16': {0: nan, 1: nan, 2: nan, 3: nan, 4: nan, 5: nan, 6: nan, 7: nan}}

Created a specimen excel of what I have

VS

An excel of transformed data

Body:
You could try to remove the unwanted rows like this.

df= df[~df['first_column_name'].str.startswith(('Company name','Account Name','Account No.','cabinet_name'))]


问:
C# Beginner, trying to change a fixed background color of a form with text in a textbox
I am a total beginner with c#, i am learning with Udemy.

I have done just a little start but now i want to test for my own.

i have learned how to use a button to change the background color of a form.

```<code>BackColor = Color.Red; etc.
</code>```

I am now trying to make a textbox where i can write in for example Red, Blue, Green ect and the click a button, then the form will change to that color.
I want to have fixed colors i can choose from so i am guessing i need to make fixed colors in the formload "tab"?

```<code>private void FrmColorCalculator_Load(object sender, EventArgs e)

            Color red = Color.Red;
            Color green = Color.Green;
</code>```

should this be in formload? how to make fixed colors? i get an errormessages saying "cannot convert system.drawing.color to string, but thats not what i want to do, i want the color to change.

If someone would be willing to kick me in the right direction?

答:
Idle_Mind’s answer can help you change the background color to the color you type in textbox.

If you want to choose fixed colors you can use combobox instead of textbox.

Here is the code:

```<code>public Form1()
    {
        InitializeComponent();
        comboBox1.Items.Add("Red");
        comboBox1.Items.Add("Blue");
        comboBox1.Items.Add("Green");
        comboBox1.Items.Add("Yellow");
    }

    private void button1_Click(object sender, EventArgs e)
    {
            this.BackColor = Color.FromName(comboBox1.Text);
    }
</code>```

Body:
I am a total beginner with c#, i am learning with Udemy.

I have done just a little start but now i want to test for my own.

i have learned how to use a button to change the background color of a form.

BackColor = Color.Red; etc.

I am now trying to make a textbox where i can write in for example Red, Blue, Green ect and the click a button, then the form will change to that color.
I want to have fixed colors i can choose from so i am guessing i need to make fixed colors in the formload "tab"?

private void FrmColorCalculator_Load(object sender, EventArgs e)

            Color red = Color.Red;
            Color green = Color.Green;

should this be in formload? how to make fixed colors? i get an errormessages saying "cannot convert system.drawing.color to string, but thats not what i want to do, i want the color to change.

If someone would be willing to kick me in the right direction?

Body:
Idle_Mind’s answer can help you change the background color to the color you type in textbox.

If you want to choose fixed colors you can use combobox instead of textbox.

Here is the code:

public Form1()
    {
        InitializeComponent();
        comboBox1.Items.Add("Red");
        comboBox1.Items.Add("Blue");
        comboBox1.Items.Add("Green");
        comboBox1.Items.Add("Yellow");
    }

    private void button1_Click(object sender, EventArgs e)
    {
            this.BackColor = Color.FromName(comboBox1.Text);
    }


问:
how to connect uvc camera with agora video call

i am tried to stream video from uvc camera with agora video call api. but it doesn't work . but the uvc camera preview show proferly on '''''' .

public class VideoChatViewActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent, CameraViewInterface.Callback{
private static final String TAG = VideoChatViewActivity.class.getSimpleName();

```<code>  private static final int PERMISSION_REQ_ID = 22;

  // Permission WRITE_EXTERNAL_STORAGE is not mandatory
  // for Agora RTC SDK, just in case if you wanna save
  // logs to external sdcard.
  private static final String[] REQUESTED_PERMISSIONS = {
          Manifest.permission.RECORD_AUDIO,
          Manifest.permission.CAMERA
  };

  private RtcEngine mRtcEngine;
  private boolean mCallEnd;
  private boolean mMuted;

  private FrameLayout mLocalContainer;
  private RelativeLayout mRemoteContainer;
  private VideoCanvas mLocalVideo;
  private VideoCanvas mRemoteVideo;

  private ImageView mCallBtn;
  private ImageView mMuteBtn;
  private ImageView mSwitchCameraBtn;

  // Customized logger view
  private LoggerRecyclerView mLogView;

  private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {

      @Override
      public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("Join channel success, uid: " + (uid & 0xFFFFFFFFL));
              }
          });
      }

      @Override
      public void onUserJoined(final int uid, int elapsed) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
                  setupRemoteVideo(uid);
              }
          });
      }

      @Override
      public void onUserOffline(final int uid, int reason) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("User offline, uid: " + (uid & 0xFFFFFFFFL));
                  onRemoteUserLeft(uid);
              }
          });
      }
  };

  private void setupRemoteVideo(int uid) {
      ViewGroup parent = mRemoteContainer;
      if (parent.indexOfChild(mLocalVideo.view) > -1) {
          parent = mLocalContainer;
      }

      if (mRemoteVideo != null) {
          return;
      }

            SurfaceView view = RtcEngine.CreateRendererView(getBaseContext());
      view.setZOrderMediaOverlay(parent == mLocalContainer);
      parent.addView(view);
      mRemoteVideo = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, uid);
      // Initializes the video view of a remote user.
      mRtcEngine.setupRemoteVideo(mRemoteVideo);
  }

  private void onRemoteUserLeft(int uid) {
      if (mRemoteVideo != null && mRemoteVideo.uid == uid) {
          removeFromParent(mRemoteVideo);
          // Destroys remote view
          mRemoteVideo = null;
      }
  }

  //usb
  private static final int DEFAULT_CAPTURE_WIDTH = 1280;
  private static final int DEFAULT_CAPTURE_HEIGHT = 720;

  @BindView(R.id.camer_view)
  public View mTextureView;
  private static final String TAG1 = "Debug";
  private UVCCameraHelper mCameraHelper;

  private CameraViewInterface mUVCCameraView;
  private AlertDialog mDialog;

  private boolean isRequest;
  private boolean isPreview;
  private UVCCameraHelper.OnMyDevConnectListener listener = new UVCCameraHelper.OnMyDevConnectListener() {

      @Override
      public void onAttachDev(UsbDevice device) {
          // request open permission
          if (!isRequest) {
              isRequest = true;
              if (mCameraHelper != null) {
                  mCameraHelper.requestPermission(0);
              }
          }
      }

      @Override
      public void onDettachDev(UsbDevice device) {
          // close camera
          if (isRequest) {
              isRequest = false;
              mCameraHelper.closeCamera();
              showShortMsg(device.getDeviceName() + " is out");
          }
      }

      @Override
      public void onConnectDev(UsbDevice device, boolean isConnected) {
          if (!isConnected) {
              showShortMsg("fail to connect,please check resolution params");
              isPreview = false;
          } else {
              isPreview = true;
              showShortMsg("connecting");
              // initialize seekbar
              // need to wait UVCCamera initialize over
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          Thread.sleep(2500);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      Looper.prepare();
                      if(mCameraHelper != null && mCameraHelper.isCameraOpened()) {

                      }
                      Looper.loop();
                  }
              }).start();
          }
      }

      @Override
      public void onDisConnectDev(UsbDevice device) {
          showShortMsg("disconnecting");
      }
  };
  //usb

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_video_chat_view);
      ButterKnife.bind(this);//uvc
      initUI();

      mUVCCameraView = (CameraViewInterface) mTextureView;
      mUVCCameraView.setCallback(this);
      //mLocalContainer.setCallback(this);
      mCameraHelper = UVCCameraHelper.getInstance();
      mCameraHelper.setDefaultPreviewSize(1280,720);
      mCameraHelper.initUSBMonitor(this, mUVCCameraView, listener);
      mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
          @Override
          public void onPreviewResult(byte[] bytes) {
              try {

                  AgoraVideoFrame frame = new AgoraVideoFrame();
                  frame.buf = bytes;
                  frame.format = AgoraVideoFrame.FORMAT_NV21;

                  frame.stride = DEFAULT_CAPTURE_WIDTH;
                  frame.height = DEFAULT_CAPTURE_HEIGHT;

                  frame.timeStamp = System.currentTimeMillis();

                  mRtcEngine.pushExternalVideoFrame(frame);

              }catch (Exception e){
                  e.printStackTrace();
              }
          }
      });
      // Ask for permissions at runtime.
      // This is just an example set of permissions. Other permissions
      // may be needed, and please refer to our online documents.
      if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
              checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)) {
          initEngineAndJoinChannel();

      }
  }

  private void initUI() {
      mLocalContainer = findViewById(R.id.local_video_view_container);
      mRemoteContainer = findViewById(R.id.remote_video_view_container);

      mCallBtn = findViewById(R.id.btn_call);
      mMuteBtn = findViewById(R.id.btn_mute);
      mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);

      mLogView = findViewById(R.id.log_recycler_view);

      // Sample logs are optional.
      showSampleLogs();
  }

  private void showSampleLogs() {
      mLogView.logI("Welcome to Agora 1v1 video call");
      mLogView.logW("You will see custom logs here");
      mLogView.logE("You can also use this to show errors");
  }

  private boolean checkSelfPermission(String permission, int requestCode) {
      if (ContextCompat.checkSelfPermission(this, permission) !=
              PackageManager.PERMISSION_GRANTED) {
          ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
          return false;
      }

      return true;
  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                                         @NonNull String[] permissions, @NonNull int[] grantResults) {
      if (requestCode == PERMISSION_REQ_ID) {
          if (grantResults[0] != PackageManager.PERMISSION_GRANTED ||
                  grantResults[1] != PackageManager.PERMISSION_GRANTED ||
                  grantResults[2] != PackageManager.PERMISSION_GRANTED) {
              showLongToast("Need permissions " + Manifest.permission.RECORD_AUDIO +
                      "/" + Manifest.permission.CAMERA);
              finish();
              return;
          }

          // Here we continue only if all permissions are granted.
          // The permissions can also be granted in the system settings manually.
          initEngineAndJoinChannel();
      }
  }

  private void showLongToast(final String msg) {
      this.runOnUiThread(new Runnable() {
          @Override
          public void run() {
              Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
          }
      });
  }

  private void initEngineAndJoinChannel() {

      initializeEngine();
      setupVideoConfig();
      setupLocalVideo();
      joinChannel();
  }

  private void initializeEngine() {
      try {
          mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
      } catch (Exception e) {
          Log.e(TAG, Log.getStackTraceString(e));
          throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
      }
  }

  private void setupVideoConfig() {

      mRtcEngine.enableVideo();

      mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
              VideoEncoderConfiguration.VD_640x360,
              VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
              VideoEncoderConfiguration.STANDARD_BITRATE,
              VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
  }

  private void setupLocalVideo() {
</code>```

.
SurfaceView view = RtcEngine.CreateRendererView(getBaseContext());
view.setZOrderMediaOverlay(true);
mLocalContainer.addView(view);
mLocalVideo = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, 0);
mRtcEngine.setupLocalVideo(mLocalVideo);
}

```<code>  private void joinChannel() {

      String token = getString(R.string.agora_access_token);
      if (TextUtils.isEmpty(token) || TextUtils.equals(token, "#YOUR ACCESS TOKEN#")) {
          token = null; // default, no token
      }
      mRtcEngine.joinChannel(token, "streaming", "Extra Optional Data", 0);
  }

  @Override
  protected void onDestroy() {
      super.onDestroy();
      if (!mCallEnd) {
          leaveChannel();
      }

      RtcEngine.destroy();
  }

  private void leaveChannel() {
      mRtcEngine.leaveChannel();
  }

  public void onLocalAudioMuteClicked(View view) {
      mMuted = !mMuted;
      mRtcEngine.muteLocalAudioStream(mMuted);
      int res = mMuted ? R.drawable.btn_mute : R.drawable.btn_unmute;
      mMuteBtn.setImageResource(res);
  }

  public void onSwitchCameraClicked(View view) {
      mRtcEngine.switchCamera();
  }

  public void onCallClicked(View view) {
      if (mCallEnd) {
          startCall();
          mCallEnd = false;
          mCallBtn.setImageResource(R.drawable.btn_endcall);
      } else {
          endCall();
          mCallEnd = true;
          mCallBtn.setImageResource(R.drawable.btn_startcall);
      }

      showButtons(!mCallEnd);
  }

  private void startCall() {
      setupLocalVideo();
      joinChannel();
  }

  private void endCall() {
      removeFromParent(mLocalVideo);
      mLocalVideo = null;
      removeFromParent(mRemoteVideo);
      mRemoteVideo = null;
      leaveChannel();
  }

  private void showButtons(boolean show) {
      int visibility = show ? View.VISIBLE : View. SurfaceView view .GONE;
      mMuteBtn.setVisibility(visibility);
      mSwitchCameraBtn.setVisibility(visibility);
  }

  private ViewGroup removeFromParent(VideoCanvas canvas) {
      if (canvas != null) {
          ViewParent parent = canvas.view.getParent();
          if (parent != null) {
              ViewGroup group = (ViewGroup) parent;
              group.removeView(canvas.view);
              return group;
          }
      }
      return null;
  }

  private void switchView(VideoCanvas canvas) {
      ViewGroup parent = removeFromParent(canvas);
      if (parent == mLocalContainer) {
          if (canvas.view instanceof SurfaceView) {
              ((SurfaceView) canvas.view).setZOrderMediaOverlay(false);
          }
          mRemoteContainer.addView(canvas.view);
      } else if (parent == mRemoteContainer) {
          if (canvas.view instanceof SurfaceView) {
              ((SurfaceView) canvas.view).setZOrderMediaOverlay(true);
          }
          mLocalContainer.addView(canvas.view);
      }
  }

  public void onLocalContainerClick(View view) {
      switchView(mLocalVideo);
      switchView(mRemoteVideo);
  }

  ///uvc

  @Override
  protected void onStart() {
      super.onStart();
      // step.2 register USB event broadcast
      if (mCameraHelper != null) {
          mCameraHelper.registerUSB();
      }
  }

  @Override
  protected void onStop() {
      super.onStop();
      // step.3 unregister USB event broadcast
      if (mCameraHelper != null) {
          mCameraHelper.unregisterUSB();
      }
  }

  private void showShortMsg(String msg) {
      //
      Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  }

  @Override
  public USBMonitor getUSBMonitor(){   return mCameraHelper.getUSBMonitor();
  }

  @Override
  public void onDialogResult(boolean canceled) {
      if (canceled) {
          showShortMsg("cancel");
      }
  }

  @Override
  public void onSurfaceCreated(CameraViewInterface cameraViewInterface, Surface surface) {
      if (!isPreview && mCameraHelper.isCameraOpened()) {
          mCameraHelper.startPreview(mUVCCameraView);
          isPreview = true;
      }
  }

  @Override
  public void onSurfaceChanged(CameraViewInterface cameraViewInterface, Surface surface, int i, int i1) {

  }

  @Override
  public void onSurfaceDestroy(CameraViewInterface cameraViewInterface, Surface surface) {
      if (isPreview && mCameraHelper.isCameraOpened()) {
          mCameraHelper.stopPreview();
          isPreview = false;
      }
  }
</code>```

}

答:
```<code>@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_video_chat_view);
    initUI();

    // Ask for permissions at runtime.
    // This is just an example set of permissions. Other permissions
    // may be needed, and please refer to our online documents.
    if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
            checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)) {
        initEngineAndJoinChannel();
    }

    //xiaobing add
    final View view = findViewById(R.id.camera_view);
    mUVCCameraView = (CameraViewInterface)view;
    mUSBMonitor = new USBMonitor(this, mOnDeviceConnectListener);
    mUVCCameraView.setAspectRatio(previewWidth / (float)previewHeight);
    mCameraHandler = UVCCameraHandler.createHandler(this,
            mUVCCameraView, previewWidth,
            previewHeight, BANDWIDTH_FACTORS[0],
            firstDataCallBack);

}
//xiaobing add
private void startPreview() {
    final SurfaceTexture st = mUVCCameraView.getSurfaceTexture();
    mCameraHandler.startPreview(new Surface(st));

}
//xiaobing add
UvcCameraDataCallBack firstDataCallBack = new UvcCameraDataCallBack() {
    @Override
    public void getData(byte[] data) {
        if (DEBUG) {
            Log.v(TAG, "data callback:" + data.length);
        }
        AgoraVideoFrame frame = new AgoraVideoFrame();
        frame.buf = data;
        frame.format = AgoraVideoFrame.FORMAT_NV12;

        frame.stride = previewWidth;
        frame.height = previewHeight;

        frame.timeStamp = System.currentTimeMillis();

        mRtcEngine.pushExternalVideoFrame(frame);

    }
};
//xiaobing add
@Override
protected void onStart() {
    super.onStart();
    if (DEBUG) Log.v(TAG, "onStart:");
    mUSBMonitor.register();
    if (mUVCCameraView != null)
        mUVCCameraView.onResume();
    if (!mCameraHandler.isOpened()) {

        UsbManager um = (UsbManager) (getSystemService(Context.USB_SERVICE));
        HashMap<String, UsbDevice> map = um.getDeviceList();
        ArrayList<String> names = new ArrayList<>();
        final ArrayList<UsbDevice> devices = new ArrayList<>();
        for(Map.Entry<String, UsbDevice> item : map.entrySet()) {
            String name = item.getValue().getProductName();
            String vid = Integer.toHexString(item.getValue().getVendorId());
            String pid = Integer.toHexString(item.getValue().getProductId());
            String all = "" + name + " VID:" + vid
                    + " PID:" + pid;
            Log.v("xiaobing", "all:" + all);
            names.add(all);
            devices.add(item.getValue());
            if(item.getValue().getProductId()==1383 && (item.getValue().getVendorId() == 3034)){
                mDev = item.getValue();
                mUSBMonitor.requestPermission(mDev);

                //为了同时支持手机和眼镜，只有获得了眼镜的设备才选择本地视频
                mRtcEngine.setExternalVideoSource(true, true, true);
                mLogView.logI("使用USB摄像头！");

                break;
            }
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
</code>```

Body:
i am tried to stream video from uvc camera with agora video call api. but it doesn't work . but the uvc camera preview show proferly on '''''' .

public class VideoChatViewActivity extends AppCompatActivity implements CameraDialog.CameraDialogParent, CameraViewInterface.Callback{
private static final String TAG = VideoChatViewActivity.class.getSimpleName();

  private static final int PERMISSION_REQ_ID = 22;

  // Permission WRITE_EXTERNAL_STORAGE is not mandatory
  // for Agora RTC SDK, just in case if you wanna save
  // logs to external sdcard.
  private static final String[] REQUESTED_PERMISSIONS = {
          Manifest.permission.RECORD_AUDIO,
          Manifest.permission.CAMERA
  };

  private RtcEngine mRtcEngine;
  private boolean mCallEnd;
  private boolean mMuted;

  private FrameLayout mLocalContainer;
  private RelativeLayout mRemoteContainer;
  private VideoCanvas mLocalVideo;
  private VideoCanvas mRemoteVideo;

  private ImageView mCallBtn;
  private ImageView mMuteBtn;
  private ImageView mSwitchCameraBtn;

  // Customized logger view
  private LoggerRecyclerView mLogView;

  private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {

      @Override
      public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("Join channel success, uid: " + (uid & 0xFFFFFFFFL));
              }
          });
      }

      @Override
      public void onUserJoined(final int uid, int elapsed) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
                  setupRemoteVideo(uid);
              }
          });
      }

      @Override
      public void onUserOffline(final int uid, int reason) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  mLogView.logI("User offline, uid: " + (uid & 0xFFFFFFFFL));
                  onRemoteUserLeft(uid);
              }
          });
      }
  };

  private void setupRemoteVideo(int uid) {
      ViewGroup parent = mRemoteContainer;
      if (parent.indexOfChild(mLocalVideo.view) > -1) {
          parent = mLocalContainer;
      }

      if (mRemoteVideo != null) {
          return;
      }

            SurfaceView view = RtcEngine.CreateRendererView(getBaseContext());
      view.setZOrderMediaOverlay(parent == mLocalContainer);
      parent.addView(view);
      mRemoteVideo = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, uid);
      // Initializes the video view of a remote user.
      mRtcEngine.setupRemoteVideo(mRemoteVideo);
  }

  private void onRemoteUserLeft(int uid) {
      if (mRemoteVideo != null && mRemoteVideo.uid == uid) {
          removeFromParent(mRemoteVideo);
          // Destroys remote view
          mRemoteVideo = null;
      }
  }

  //usb
  private static final int DEFAULT_CAPTURE_WIDTH = 1280;
  private static final int DEFAULT_CAPTURE_HEIGHT = 720;

  @BindView(R.id.camer_view)
  public View mTextureView;
  private static final String TAG1 = "Debug";
  private UVCCameraHelper mCameraHelper;

  private CameraViewInterface mUVCCameraView;
  private AlertDialog mDialog;

  private boolean isRequest;
  private boolean isPreview;
  private UVCCameraHelper.OnMyDevConnectListener listener = new UVCCameraHelper.OnMyDevConnectListener() {

      @Override
      public void onAttachDev(UsbDevice device) {
          // request open permission
          if (!isRequest) {
              isRequest = true;
              if (mCameraHelper != null) {
                  mCameraHelper.requestPermission(0);
              }
          }
      }

      @Override
      public void onDettachDev(UsbDevice device) {
          // close camera
          if (isRequest) {
              isRequest = false;
              mCameraHelper.closeCamera();
              showShortMsg(device.getDeviceName() + " is out");
          }
      }

      @Override
      public void onConnectDev(UsbDevice device, boolean isConnected) {
          if (!isConnected) {
              showShortMsg("fail to connect,please check resolution params");
              isPreview = false;
          } else {
              isPreview = true;
              showShortMsg("connecting");
              // initialize seekbar
              // need to wait UVCCamera initialize over
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                          Thread.sleep(2500);
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                      Looper.prepare();
                      if(mCameraHelper != null && mCameraHelper.isCameraOpened()) {

                      }
                      Looper.loop();
                  }
              }).start();
          }
      }

      @Override
      public void onDisConnectDev(UsbDevice device) {
          showShortMsg("disconnecting");
      }
  };
  //usb

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_video_chat_view);
      ButterKnife.bind(this);//uvc
      initUI();

      mUVCCameraView = (CameraViewInterface) mTextureView;
      mUVCCameraView.setCallback(this);
      //mLocalContainer.setCallback(this);
      mCameraHelper = UVCCameraHelper.getInstance();
      mCameraHelper.setDefaultPreviewSize(1280,720);
      mCameraHelper.initUSBMonitor(this, mUVCCameraView, listener);
      mCameraHelper.setOnPreviewFrameListener(new AbstractUVCCameraHandler.OnPreViewResultListener() {
          @Override
          public void onPreviewResult(byte[] bytes) {
              try {

                  AgoraVideoFrame frame = new AgoraVideoFrame();
                  frame.buf = bytes;
                  frame.format = AgoraVideoFrame.FORMAT_NV21;

                  frame.stride = DEFAULT_CAPTURE_WIDTH;
                  frame.height = DEFAULT_CAPTURE_HEIGHT;

                  frame.timeStamp = System.currentTimeMillis();

                  mRtcEngine.pushExternalVideoFrame(frame);

              }catch (Exception e){
                  e.printStackTrace();
              }
          }
      });
      // Ask for permissions at runtime.
      // This is just an example set of permissions. Other permissions
      // may be needed, and please refer to our online documents.
      if (checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID) &&
              checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)) {
          initEngineAndJoinChannel();

      }
  }

  private void initUI() {
      mLocalContainer = findViewById(R.id.local_video_view_container);
      mRemoteContainer = findViewById(R.id.remote_video_view_container);

      mCallBtn = findViewById(R.id.btn_call);
      mMuteBtn = findViewById(R.id.btn_mute);
      mSwitchCameraBtn = findViewById(R.id.btn_switch_camera);

      mLogView = findViewById(R.id.log_recycler_view);

      // Sample logs are optional.
      showSampleLogs();
  }

  private void showSampleLogs() {
      mLogView.logI("Welcome to Agora 1v1 video call");
      mLogView.logW("You will see custom logs here");
      mLogView.logE("You can also use this to show errors");
  }

  private boolean checkSelfPermission(String permission, int requestCode) {
      if (ContextCompat.checkSelfPermission(this, permission) !=
              PackageManager.PERMISSION_GRANTED) {
          ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
          return false;
      }

      return true;
  }

  @Override
  public void onRequestPermissionsResult(int requestCode,
                                         @NonNull String[] permissions, @NonNull int[] grantResults) {
      if (requestCode == PERMISSION_REQ_ID) {
          if (grantResults[0] != PackageManager.PERMISSION_GRANTED ||
                  grantResults[1] != PackageManager.PERMISSION_GRANTED ||
                  grantResults[2] != PackageManager.PERMISSION_GRANTED) {
              showLongToast("Need permissions " + Manifest.permission.RECORD_AUDIO +
                      "/" + Manifest.permission.CAMERA);
              finish();
              return;
          }

          // Here we continue only if all permissions are granted.
          // The permissions can also be granted in the system settings manually.
          initEngineAndJoinChannel();
      }
  }

  private void showLongToast(final String msg) {
      this.runOnUiThread(new Runnable() {
          @Override
          public void run() {
              Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
          }
      });
  }

  private void initEngineAndJoinChannel() {

      initializeEngine();
      setupVideoConfig();
      setupLocalVideo();
      joinChannel();
  }

  private void initializeEngine() {
      try {
          mRtcEngine = RtcEngine.create(getBaseContext(), getString(R.string.agora_app_id), mRtcEventHandler);
      } catch (Exception e) {
          Log.e(TAG, Log.getStackTraceString(e));
          throw new RuntimeException("NEED TO check rtc sdk init fatal error\n" + Log.getStackTraceString(e));
      }
  }

  private void setupVideoConfig() {

      mRtcEngine.enableVideo();

      mRtcEngine.setVideoEncoderConfiguration(new VideoEncoderConfiguration(
              VideoEncoderConfiguration.VD_640x360,
              VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15,
              VideoEncoderConfiguration.STANDARD_BITRATE,
              VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_FIXED_PORTRAIT));
  }

  private void setupLocalVideo() {

.
SurfaceView view = RtcEngine.CreateRendererView(getBaseContext());
view.setZOrderMediaOverlay(true);
mLocalContainer.addView(view);
mLocalVideo = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, 0);
mRtcEngine.setupLocalVideo(mLocalVideo);
}

  private void joinChannel() {

      String token = getString(R.string.agora_access_token);
      if (TextUtils.isEmpty(token) || TextUtils.equals(token, "#YOUR ACCESS TOKEN#")) {
          token = null; // default, no token
      }
      mRtcEngine.joinChannel(token, "streaming", "Extra Optional Data", 0);
  }

  @Override
  protected void onDestroy() {
      super.onDestroy();
      if (!mCallEnd) {
          leaveChannel();
      }

      RtcEngine.destroy();
  }

  private void leaveChannel() {
      mRtcEngine.leaveChannel();
  }

  public void onLocalAudioMuteClicked(View view) {
      mMuted = !mMuted;
      mRtcEngine.muteLocalAudioStream(mMuted);
      int res = mMuted ? R.drawable.btn_mute : R.drawable.btn_unmute;
      mMuteBtn.setImageResource(res);
  }

  public void onSwitchCameraClicked(View view) {
      mRtcEngine.switchCamera();
  }

  public void onCallClicked(View view) {
      if (mCallEnd) {
          startCall();
          mCallEnd = false;
          mCallBtn.setImageResource(R.drawable.btn_endcall);
      } else {
          endCall();
          mCallEnd = true;
          mCallBtn.setImageResource(R.drawable.btn_startcall);
      }

      showButtons(!mCallEnd);
  }

  private void startCall() {
      setupLocalVideo();
      joinChannel();
  }

  private void endCall() {
      removeFromParent(mLocalVideo);
      mLocalVideo = null;
      removeFromParent(mRemoteVideo);
      mRemoteVideo = null;
      leaveChannel();
  }

  private void showButtons(boolean show) {
      int visibility = show ? View.VISIBLE : View. SurfaceView view .GONE;
      mMuteBtn.setVisibility(visibility);
      mSwitchCameraBtn.setVisibility(visibility);
  }

  private ViewGroup removeFromParent(VideoCanvas canvas) {
      if (canvas != null) {
          ViewParent parent = canvas.view.getParent();
          if (parent != null) {
              ViewGroup group = (ViewGroup) parent;
              group.removeView(canvas.view);
              return group;
          }
      }
      return null;
  }

  private void switchView(VideoCanvas canvas) {
      ViewGroup parent = removeFromParent(canvas);
      if (parent == mLocalContainer) {
          if (canvas.view instanceof SurfaceView) {
              ((SurfaceView) canvas.view).setZOrderMediaOverlay(false);
          }
          mRemoteContainer.addView(canvas.view);
      } else if (parent == mRemoteContainer) {
          if (canvas.view instanceof SurfaceView) {
              ((SurfaceView) canvas.view).setZOrderMediaOverlay(true);
          }
          mLocalContainer.addView(canvas.view);
      }
  }

  public void onLocalContainerClick(View view) {
      switchView(mLocalVideo);
      switchView(mRemoteVideo);
  }

  ///uvc

  @Override
  protected void onStart() {
      super.onStart();
      // step.2 register USB event broadcast
      if (mCameraHelper != null) {
          mCameraHelper.registerUSB();
      }
  }

  @Override
  protected void onStop() {
      super.onStop();
      // step.3 unregister USB event broadcast
      if (mCameraHelper != null) {
          mCameraHelper.unregisterUSB();
      }
  }

  private void showShortMsg(String msg) {
      //
      Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  }

  @Override
  public USBMonitor getUSBMonitor(){   return mCameraHelper.getUSBMonitor();
  }

  @Override
  public void onDialogResult(boolean canceled) {
      if (canceled) {
          showShortMsg("cancel");
      }
  }

  @Override
  public void onSurfaceCreated(CameraViewInterface cameraViewInterface, Surface surface) {
      if (!isPreview && mCameraHelper.isCameraOpened()) {
          mCameraHelper.startPreview(mUVCCameraView);
          isPreview = true;
      }
  }

  @Override
  public void onSurfaceChanged(CameraViewInterface cameraViewInterface, Surface surface, int i, int i1) {

  }

  @Override
  public void onSurfaceDestroy(CameraViewInterface cameraViewInterface, Surface surface) {
      if (isPreview && mCameraHelper.isCameraOpened()) {
          mCameraHelper.stopPreview();
          isPreview = false;
      }
  }

}


问:
How do you change the src of an image tag if a button tag is clicked?
If I were to create an image and give it the source of "box.png", using CSS or Javascript, how could I make a button change the source of the image to "package.png"?</p>

答:
Clicking the button changes the src attribute of the  element in the event listener.

let button = document.getElementById('toggleButton');
let logo = document.getElementById('logo');

let darkImageURL = "https://cdn-icons-png.flaticon.com/512/196/196685.png";
let lightImageURL = "https://cdn-icons-png.flaticon.com/512/169/169367.png";

button.addEventListener('click', function(event) {
  if(this.innerHTML === "Dark") {
    document.body.style.background = "black";
    this.innerHTML = "Light";
    logo.src = darkImageURL;
  }
  else {
    document.body.style.background = "white";
    this.innerHTML = "Dark";
    logo.src = lightImageURL;
  }
});```
<pre class="snippet-code-html lang-html prettyprint-override"><code><body>
  <button id="toggleButton">Dark</button>

  <img id="logo" class="nav_logo" src="https://cdn-icons-png.flaticon.com/512/169/169367.png" alt="original logo" width="100" height="100"/>
</body></code>```

Body:
Clicking the button changes the src attribute of the <img> element in the event listener.

let button = document.getElementById('toggleButton');
let logo = document.getElementById('logo');

let darkImageURL = "https://cdn-icons-png.flaticon.com/512/196/196685.png";
let lightImageURL = "https://cdn-icons-png.flaticon.com/512/169/169367.png";

button.addEventListener('click', function(event) {
  if(this.innerHTML === "Dark") {
    document.body.style.background = "black";
    this.innerHTML = "Light";
    logo.src = darkImageURL;
  }
  else {
    document.body.style.background = "white";
    this.innerHTML = "Dark";
    logo.src = lightImageURL;
  }
});

<body>
  <button id="toggleButton">Dark</button>

  <img id="logo" class="nav_logo" src="https://cdn-icons-png.flaticon.com/512/169/169367.png" alt="original logo" width="100" height="100"/>
</body>