问:
Laravel full text search
I'm trying to implement a full text search query to the database. This is in the specification that my client sent me:

```<code>"The free text search limits the result of the data table to records with a matching first
name, last name, country, city, state, or zip code. If several words are input,
each word must match one of the columns for a record to be visible."
</code>```

I made some very ugly spaghetti code in my controller to try if it works:

```<code>public function search($searchTerms){
        $searchTerms = explode(' ', $searchTerms);
        $results = array();
        foreach ($searchTerms as $searchTerm) {
            if (!People::where('firstname', 'LIKE', '%'.$searchTerm.'%')->get()->isEmpty()) {
                array_push($results, People::where('firstname', 'LIKE', '%'.$searchTerm.'%')->get());
            }
            else if (!People::where('lastname', 'LIKE', '%'.$searchTerm.'%')->get()->isEmpty()) {
                array_push($results, People::where('lastname', 'LIKE', '%'.$searchTerm.'%')->get());
            }
        }
        return $results;
    }
</code>```

And this is my call to this function:

```<code>$data->people = $this->search(Input::get('search'));
</code>```

The problem is that if there is no search input, I use this to get all data:

```<code>$data->people = People::orderBy($order)->paginate(10);
</code>```

And by getting the search results as an array, I get the following error in my views:

```<code>Undefined property: Illuminate\Database\Eloquent\Collection::$firstname (View: /home/projects/pplproject/app/views/index.blade.php)
</code>```

How should this be implemented in the Laravel way?

答:
try this:</p>
```<code>$query = People::query();
    $searches = explode(' ', $request->query('q'));

                if (isset($searches)) {
                    foreach ($searches as $search) {
                        $query->where(function ($q) use ($search) {
                            $q->where('firstname', 'ilike', '%' . $search . '%')
                                ->orWhere('lastname', 'ilike', '%' . $search . '%');
                        });
                    }
                }

                $data = $query->get();

                return ([
                    'success'   => true,
                    'response'  => $data,
                    'message'   => 'Your message here'
                ]);
</code>```

Title: Laravel full text search

Body:
I'm trying to implement a full text search query to the database. This is in the specification that my client sent me:

"The free text search limits the result of the data table to records with a matching first
name, last name, country, city, state, or zip code. If several words are input,
each word must match one of the columns for a record to be visible."

I made some very ugly spaghetti code in my controller to try if it works:

public function search($searchTerms){
        $searchTerms = explode(' ', $searchTerms);
        $results = array();
        foreach ($searchTerms as $searchTerm) {
            if (!People::where('firstname', 'LIKE', '%'.$searchTerm.'%')->get()->isEmpty()) {
                array_push($results, People::where('firstname', 'LIKE', '%'.$searchTerm.'%')->get());
            }
            else if (!People::where('lastname', 'LIKE', '%'.$searchTerm.'%')->get()->isEmpty()) {
                array_push($results, People::where('lastname', 'LIKE', '%'.$searchTerm.'%')->get());
            }
        }
        return $results;
    }

And this is my call to this function:

$data->people = $this->search(Input::get('search'));

The problem is that if there is no search input, I use this to get all data:

$data->people = People::orderBy($order)->paginate(10);

And by getting the search results as an array, I get the following error in my views:

Undefined property: Illuminate\Database\Eloquent\Collection::$firstname (View: /home/projects/pplproject/app/views/index.blade.php)

How should this be implemented in the Laravel way?

Body:
try this:

$query = People::query();
    $searches = explode(' ', $request->query('q'));

                if (isset($searches)) {
                    foreach ($searches as $search) {
                        $query->where(function ($q) use ($search) {
                            $q->where('firstname', 'ilike', '%' . $search . '%')
                                ->orWhere('lastname', 'ilike', '%' . $search . '%');
                        });
                    }
                }

                $data = $query->get();

                return ([
                    'success'   => true,
                    'response'  => $data,
                    'message'   => 'Your message here'
                ]);


来源: stackexchange

问:
Saving data from a switch used as a menu in C#?
I'm trying to make a bank program that is going to have the switch as a menu that i can call the different cases from. But the problem is that i don't know how i can call one of the cases in the switch, and then let the user enter data that will be saved the variable.

The thing is if i let the user put like 100 into his account, the balance says it still is 0.

It's probably because I've set the balance (saldo) to zero and when the menu loops it gets that value? But I don't know how to do since I have to give the saldo a value to start with.

Here is my code:

```<code>class Konto
{
    static void Main(string[] args)
    {
        Console.WriteLine("Välkommen till Andreas bank!");
        bool avsluta = true;

        while (avsluta)
        {
            Console.WriteLine("Ange det alternativ för vad du vill göra: ");
            Console.WriteLine("[I]nsättning");
            Console.WriteLine("[U]ttag");
            Console.WriteLine("[S]aldo");
            Console.WriteLine("[R]äntebetalning");
            Console.WriteLine("[A]vsluta");

            char menuAlternativ = Convert.ToChar(Console.ReadLine());
            Console.WriteLine(GetMenu(menuAlternativ));

            Console.ReadLine();
        }
    }

    static string GetMenu(char menu)
    {
        string menuChoice;
        double insättning;
        double saldo = 0;
        double uttag;

        switch (menu)
        {
            case 'I':
                Console.WriteLine("Ange hur mycket du vill sätta in: ");
                insättning = Convert.ToInt32(Console.ReadLine());
                saldo = insättning + saldo;
                menuChoice = "Du har satt in " + insättning + " Kronor.";
                break;
            case 'U':
                Console.WriteLine("Ange hur mycket du vill ta ut: ");
                uttag = Convert.ToInt32(Console.ReadLine());
                menuChoice = "Du har tagit ut " + uttag + " Kronor.";
                break;
            case 'S':
                menuChoice = "Ditt saldo är: " + saldo + " Kronor.";
                break;

            case 'R':
                double Summa = 0, ränta, sparandeÅr, totaltSparande;
                Console.Write("Skriv in ditt årliga sparande: ");
                totaltSparande = Convert.ToDouble(Console.ReadLine());
                Console.Write("Ange räntan per år: ");
                ränta = Convert.ToDouble(Console.ReadLine()) / 100;
                Console.Write("Ange antal år du vill spara: ");
                sparandeÅr = Convert.ToDouble(Console.ReadLine());

                //Om antal år är mindre än antal år användaren vill spara, öka med 1 år tills användarens antal år är nådd.
                for (int år = 1; år < sparandeÅr + 1; år++)
                {
                    Summa = totaltSparande * Math.Pow((1 + ränta / sparandeÅr), (sparandeÅr * år));
                    Console.Write("Ditt totala sparande för år {0} " + " är: {1:F0}. \n", år, Summa);
                }
                menuChoice = "Så här kommer din ränta att se ut.";
                break;

            case 'A':
                menuChoice = "Du har valt att avsluta programmet.";
                break;

            default:
                menuChoice = "Invalid menu character";
                break;

        }

        return menuChoice;
    }
}
</code>```

答:
You must add a global variable double saldo=0, in main class .

try this

```<code> class Program
    {
        static double saldo = 0;
        static void Main(string[] args)
        {

           string sentence = "This is a goodday";
           string word = "goods";
          // Console.WriteLine(checkString(sentence,word).ToString());

        Console.WriteLine("Välkommen till Andreas bank!");
        bool avsluta = true;

        while (avsluta)
        {
            Console.WriteLine("Imposta l'opzione per ciò che vuoi fare: ");
            Console.WriteLine("[I]Depositare");
            Console.WriteLine("[U]presa");
            Console.WriteLine("[S]aldo");
            Console.WriteLine("[R]pagamento di interessi");
            Console.WriteLine("[A]fine");

            char menuAlternativ = Convert.ToChar(Console.ReadLine());
            Console.WriteLine(GetMenu(menuAlternativ));

            Console.ReadLine();
        }

        }
    static string GetMenu(char menu)
    {

        string menuChoice;
        double insättning;

        double uttag;

        switch (menu)
        {
            case 'I':
                Console.WriteLine("Inserisci quanto vuoi depositare: ");
                insättning = Convert.ToInt32(Console.ReadLine());
                saldo = insättning + saldo;
                menuChoice = "Hai depositato " + insättning + " Corona.";
                break;
            case 'U':
                Console.WriteLine("Inserisci quanto vuoi prelevare: ");
                uttag = Convert.ToInt32(Console.ReadLine());
                menuChoice = "Hai tirato fuori" + uttag + " Corona.";
                break;
            case 'S':
                menuChoice = "Il tuo saldo è: " + saldo + " Corona.";
                break;

            case 'R':
                double Summa = 0, ränta, sparandeÅr, totaltSparande;
                Console.Write("Inserisci i tuoi risparmi annuali: ");
                totaltSparande = Convert.ToDouble(Console.ReadLine());
                Console.Write("Inserisci il tasso di interesse per anno: ");
                ränta = Convert.ToDouble(Console.ReadLine()) / 100;
                Console.Write("Inserisci il numero di anni che vuoi salvare: ");
                sparandeÅr = Convert.ToDouble(Console.ReadLine());

                //Om antal år är mindre än antal år användaren vill spara, öka med 1 år tills användarens antal år är nådd.
                for (int år = 1; år < sparandeÅr + 1; år++)
                {
                    Summa = totaltSparande * Math.Pow((1 + ränta / sparandeÅr), (sparandeÅr * år));
                    Console.Write("Il tuo risparmio totale per anni {0} " + " är: {1:F0}. \n", år, Summa);
                }
                menuChoice = "Ecco come apparirà il tuo tasso di interesse.";
                break;

            case 'A':
                menuChoice = "Hai scelto di terminare il programma.";
                break;
            default:
                menuChoice = "Invalid menu character";
                break;

        }

        return menuChoice;
    }```

Alex
```

ContentLicense: CC BY-SA 4.0

Body:
I'm trying to make a bank program that is going to have the switch as a menu that i can call the different cases from. But the problem is that i don't know how i can call one of the cases in the switch, and then let the user enter data that will be saved the variable.

The thing is if i let the user put like 100 into his account, the balance says it still is 0.

It's probably because I've set the balance (saldo) to zero and when the menu loops it gets that value? But I don't know how to do since I have to give the saldo a value to start with.

Here is my code:

class Konto
{
    static void Main(string[] args)
    {
        Console.WriteLine("Välkommen till Andreas bank!");
        bool avsluta = true;

        while (avsluta)
        {
            Console.WriteLine("Ange det alternativ för vad du vill göra: ");
            Console.WriteLine("[I]nsättning");
            Console.WriteLine("[U]ttag");
            Console.WriteLine("[S]aldo");
            Console.WriteLine("[R]äntebetalning");
            Console.WriteLine("[A]vsluta");

            char menuAlternativ = Convert.ToChar(Console.ReadLine());
            Console.WriteLine(GetMenu(menuAlternativ));

            Console.ReadLine();
        }
    }

    static string GetMenu(char menu)
    {
        string menuChoice;
        double insättning;
        double saldo = 0;
        double uttag;

        switch (menu)
        {
            case 'I':
                Console.WriteLine("Ange hur mycket du vill sätta in: ");
                insättning = Convert.ToInt32(Console.ReadLine());
                saldo = insättning + saldo;
                menuChoice = "Du har satt in " + insättning + " Kronor.";
                break;
            case 'U':
                Console.WriteLine("Ange hur mycket du vill ta ut: ");
                uttag = Convert.ToInt32(Console.ReadLine());
                menuChoice = "Du har tagit ut " + uttag + " Kronor.";
                break;
            case 'S':
                menuChoice = "Ditt saldo är: " + saldo + " Kronor.";
                break;

            case 'R':
                double Summa = 0, ränta, sparandeÅr, totaltSparande;
                Console.Write("Skriv in ditt årliga sparande: ");
                totaltSparande = Convert.ToDouble(Console.ReadLine());
                Console.Write("Ange räntan per år: ");
                ränta = Convert.ToDouble(Console.ReadLine()) / 100;
                Console.Write("Ange antal år du vill spara: ");
                sparandeÅr = Convert.ToDouble(Console.ReadLine());

                //Om antal år är mindre än antal år användaren vill spara, öka med 1 år tills användarens antal år är nådd.
                for (int år = 1; år < sparandeÅr + 1; år++)
                {
                    Summa = totaltSparande * Math.Pow((1 + ränta / sparandeÅr), (sparandeÅr * år));
                    Console.Write("Ditt totala sparande för år {0} " + " är: {1:F0}. \n", år, Summa);
                }
                menuChoice = "Så här kommer din ränta att se ut.";
                break;

            case 'A':
                menuChoice = "Du har valt att avsluta programmet.";
                break;

            default:
                menuChoice = "Invalid menu character";
                break;

        }

        return menuChoice;
    }
}

Body:
You must add a global variable double saldo=0, in main class .

try this

 class Program
    {
        static double saldo = 0;
        static void Main(string[] args)
        {

           string sentence = "This is a goodday";
           string word = "goods";
          // Console.WriteLine(checkString(sentence,word).ToString());

        Console.WriteLine("Välkommen till Andreas bank!");
        bool avsluta = true;

        while (avsluta)
        {
            Console.WriteLine("Imposta l'opzione per ciò che vuoi fare: ");
            Console.WriteLine("[I]Depositare");
            Console.WriteLine("[U]presa");
            Console.WriteLine("[S]aldo");
            Console.WriteLine("[R]pagamento di interessi");
            Console.WriteLine("[A]fine");

            char menuAlternativ = Convert.ToChar(Console.ReadLine());
            Console.WriteLine(GetMenu(menuAlternativ));

            Console.ReadLine();
        }

        }
    static string GetMenu(char menu)
    {

        string menuChoice;
        double insättning;

        double uttag;

        switch (menu)
        {
            case 'I':
                Console.WriteLine("Inserisci quanto vuoi depositare: ");
                insättning = Convert.ToInt32(Console.ReadLine());
                saldo = insättning + saldo;
                menuChoice = "Hai depositato " + insättning + " Corona.";
                break;
            case 'U':
                Console.WriteLine("Inserisci quanto vuoi prelevare: ");
                uttag = Convert.ToInt32(Console.ReadLine());
                menuChoice = "Hai tirato fuori" + uttag + " Corona.";
                break;
            case 'S':
                menuChoice = "Il tuo saldo è: " + saldo + " Corona.";
                break;

            case 'R':
                double Summa = 0, ränta, sparandeÅr, totaltSparande;
                Console.Write("Inserisci i tuoi risparmi annuali: ");
                totaltSparande = Convert.ToDouble(Console.ReadLine());
                Console.Write("Inserisci il tasso di interesse per anno: ");
                ränta = Convert.ToDouble(Console.ReadLine()) / 100;
                Console.Write("Inserisci il numero di anni che vuoi salvare: ");
                sparandeÅr = Convert.ToDouble(Console.ReadLine());

                //Om antal år är mindre än antal år användaren vill spara, öka med 1 år tills användarens antal år är nådd.
                for (int år = 1; år < sparandeÅr + 1; år++)
                {
                    Summa = totaltSparande * Math.Pow((1 + ränta / sparandeÅr), (sparandeÅr * år));
                    Console.Write("Il tuo risparmio totale per anni {0} " + " är: {1:F0}. \n", år, Summa);
                }
                menuChoice = "Ecco come apparirà il tuo tasso di interesse.";
                break;

            case 'A':
                menuChoice = "Hai scelto di terminare il programma.";
                break;
            default:
                menuChoice = "Invalid menu character";
                break;

        }

        return menuChoice;
    }```

Alex


问:
ComponentActivity ClassNotFoundException when trying to setup Instrumented tests, with Android Compose and Hilt
I'm setting up my first instrumented unit-test and getting an obscure crash in logcat.

The emulator starts and immediately crashes when the app tries to open and the unit test doesn't even run because the application wasn't in the right state.

```<code>2022-02-09 19:30:37.116 25764-25764/com.anotherday.day17.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.anotherday.day17.test, PID: 25764
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.anotherday.day17.test/androidx.activity.ComponentActivity}: java.lang.ClassNotFoundException: Didn't find class "androidx.activity.ComponentActivity" on path: DexPathList[[zip file "/data/app/~~NodQZs7v97-vYTPte3T7UQ==/com.anotherday.day17.test-25XuwB3vTwyNbSX-nlETDQ==/base.apk"],
</code>```

It seems to be looking for androidx.activity.ComponentActivity which is defined in the following gradle dependency:

 implementation 'androidx.activity:activity-compose:1.3.1'

Not sure where else to look, here's my first test and my project in git:
https://github.com/davida5/ComposeNotepad/blob/main/app/src/androidTest/java/com/anotherday/day17/navigation/NavigatorTest.kt

答:
I finally figured out the problem, needed to instantiate the compose rule such as this:

```<code>val composeRule = createAndroidComposeRule<MainActivity>()
</code>```

instead of

```<code>val composeRule = createComposeRule()
</code>```

The first (correct) call allows passing in of my Hilt annotated (@AndroidEntryPoint) Activity instead of the default ComponentActivity which is not annotated since it belongs to the framework. That's why it kept complaining about the ComponentActivity, if you look inside the createComposeRule(), that's all it does, call createAndroidComposeRule().

Body:
I'm setting up my first instrumented unit-test and getting an obscure crash in logcat.

The emulator starts and immediately crashes when the app tries to open and the unit test doesn't even run because the application wasn't in the right state.

2022-02-09 19:30:37.116 25764-25764/com.anotherday.day17.test E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.anotherday.day17.test, PID: 25764
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.anotherday.day17.test/androidx.activity.ComponentActivity}: java.lang.ClassNotFoundException: Didn't find class "androidx.activity.ComponentActivity" on path: DexPathList[[zip file "/data/app/~~NodQZs7v97-vYTPte3T7UQ==/com.anotherday.day17.test-25XuwB3vTwyNbSX-nlETDQ==/base.apk"],

It seems to be looking for androidx.activity.ComponentActivity which is defined in the following gradle dependency:

 implementation 'androidx.activity:activity-compose:1.3.1'

Not sure where else to look, here's my first test and my project in git:
https://github.com/davida5/ComposeNotepad/blob/main/app/src/androidTest/java/com/anotherday/day17/navigation/NavigatorTest.kt

Body:
I finally figured out the problem, needed to instantiate the compose rule such as this:

val composeRule = createAndroidComposeRule<MainActivity>()

instead of

val composeRule = createComposeRule()

The first (correct) call allows passing in of my Hilt annotated (@AndroidEntryPoint) Activity instead of the default ComponentActivity which is not annotated since it belongs to the framework. That's why it kept complaining about the ComponentActivity, if you look inside the createComposeRule(), that's all it does, call createAndroidComposeRule().


问:
How to launch an apk via ADB with console arguments on Android
How to launch an application with console arguments via adb on Android 10?

Search in docs https://developer.android.com/studio/command-line/adb

Googled for two days, everywhere they write what they need like this:
adb shell am start -S -D -n projectname.app/com.unity3d.player.UnityPlayerActivity --es args '"-runTests"'

Tried some more options but nothing worked

The application is a game on Unity, there I display System.Environment.GetCommandLineArgs()
directly

答:
I think this is a misunderstanding because Android apps do not have command-line arguments as all app processes are forked from the dalvik virtual machine process.

The options you set on am start are intent options, so you have to get those options e.g. in onCreate of the UnityPlayerActivity class:

```<code>String arg = intent.getStringExtra("args");
Log.d("", arg); // would in your example output "-runTests"
</code>```

Body:
I think this is a misunderstanding because Android apps do not have command-line arguments as all app processes are forked from the dalvik virtual machine process.

The options you set on am start are intent options, so you have to get those options e.g. in onCreate of the UnityPlayerActivity class:

String arg = intent.getStringExtra("args");
Log.d("", arg); // would in your example output "-runTests"


问:
Sum() slows down my query
I am using sum() inside case statement. But this slows down my query. Is there any other way for this. This is the query. Please help me.

```<code>SELECT (SUM(PRI_INS_AGING) + SUM(SEC_INS_AGING) + SUM(TER_INS_AGING)) AS INS_AGING,SUM(PAT_AGING) AS PAT_AGING FROM
                (SELECT
        CASE WHEN L.RESP_PARTY =1 AND VP.STATUS IN(3,5) AND VP.PRIMARY_PAID =0 AND VP.PRIMARY_PENDING >0 AND C.PRIMARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS PRI_INS_AGING,
        CASE WHEN L.RESP_PARTY =2 AND VP.STATUS IN(6,7,5) AND VP.SECONDARY_PAID =0 AND VP.SECONDARY_PENDING >0 AND VP.PRIMARY_PENDING <=0 AND C.SECONDARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS SEC_INS_AGING,
        CASE WHEN L.RESP_PARTY =3 AND VP.STATUS IN(8,9,5) AND VP.TERTIARY_PAID =0 AND VP.TERTIARY_PENDING >0 AND VP.PRIMARY_PENDING <=0 AND VP.SECONDARY_PENDING <=0 AND C.TERTIARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS TER_INS_AGING,
        CASE WHEN L.RESP_PARTY =4 THEN SUM(L.AMOUNT) ELSE 0 END AS PAT_AGING
        FROM VISIT_PROCEDURE VP
        JOIN CLAIM C
        ON (C.CLAIM_ID = VP.CLAIM_ID AND C.CLINIC_ID = VP.CLINIC_ID)
        JOIN LEDGER L
        ON (L.CLAIM_ID = L.CLAIM_ID AND VP.CLINIC_ID = L.CLINIC_ID)
        WHERE C.CLINIC_ID = 34847 AND L.TYPE IN(1,8,9,10,11) AND L.ACTIVE=1
        GROUP BY VP.PROCEDURE_ID,L.TYPE,L.RESP_PARTY,L.ACTIVE)T1
</code>```

Thanks
Sunil

答:
If you're looking to get the SUM() of your data, I don't see you getting it any other way. That said, this is pretty complex and you might benefit from breaking it down into a stored proc and splitting the calculations up into stages.

Btw what does slow mean here? 1 second rather than 0.001? Or, 2 minutes?

ContentLicense: CC BY-SA 3.0

Title: Sum() slows down my query

Body:
I am using sum() inside case statement. But this slows down my query. Is there any other way for this. This is the query. Please help me.

SELECT (SUM(PRI_INS_AGING) + SUM(SEC_INS_AGING) + SUM(TER_INS_AGING)) AS INS_AGING,SUM(PAT_AGING) AS PAT_AGING FROM
                (SELECT
        CASE WHEN L.RESP_PARTY =1 AND VP.STATUS IN(3,5) AND VP.PRIMARY_PAID =0 AND VP.PRIMARY_PENDING >0 AND C.PRIMARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS PRI_INS_AGING,
        CASE WHEN L.RESP_PARTY =2 AND VP.STATUS IN(6,7,5) AND VP.SECONDARY_PAID =0 AND VP.SECONDARY_PENDING >0 AND VP.PRIMARY_PENDING <=0 AND C.SECONDARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS SEC_INS_AGING,
        CASE WHEN L.RESP_PARTY =3 AND VP.STATUS IN(8,9,5) AND VP.TERTIARY_PAID =0 AND VP.TERTIARY_PENDING >0 AND VP.PRIMARY_PENDING <=0 AND VP.SECONDARY_PENDING <=0 AND C.TERTIARY_PAYER_ID >0 AND C.HIDEN=0 THEN SUM(L.AMOUNT) ELSE 0 END AS TER_INS_AGING,
        CASE WHEN L.RESP_PARTY =4 THEN SUM(L.AMOUNT) ELSE 0 END AS PAT_AGING
        FROM VISIT_PROCEDURE VP
        JOIN CLAIM C
        ON (C.CLAIM_ID = VP.CLAIM_ID AND C.CLINIC_ID = VP.CLINIC_ID)
        JOIN LEDGER L
        ON (L.CLAIM_ID = L.CLAIM_ID AND VP.CLINIC_ID = L.CLINIC_ID)
        WHERE C.CLINIC_ID = 34847 AND L.TYPE IN(1,8,9,10,11) AND L.ACTIVE=1
        GROUP BY VP.PROCEDURE_ID,L.TYPE,L.RESP_PARTY,L.ACTIVE)T1

Thanks
Sunil


问:
Chartjs sample can't be reproduced
I am looking to reproduce the result of this sample from Chartjs doc :
https://www.chartjs.org/docs/latest/samples/scales/time-line.html

What I am looking for is the scale result on x :

I use react with react-chartjs-2 and a simplified version of the example, but I managed to keep same config and data for the x axis :

```<code>import { DateTime } from 'luxon';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS, registerables } from 'chart.js';
import 'chartjs-adapter-luxon';

ChartJS.register(...registerables);

function newDate(days: number) {
  return DateTime.now().plus({ days }).toJSDate();
}

function newDateString(days: number) {
  return DateTime.now().plus({ days }).toISO();
}

const options = {
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: { display: false },
  },
  scale: {
    x: {
      type: 'time',
      time: {
        tooltipFormat: 'DD T',
      },
    },
    y: {
      type: 'linear',
      suggestedMin: 0,
      suggestedMax: 100,
      ticks: {
        stepSize: 20,
      },
    },
  },
};

const labels = [newDate(0), newDate(1), newDate(2), newDate(3), newDate(4), newDate(5), newDate(6)];
const Data = [
  {
    x: newDateString(0),
    y: 41,
  },
  {
    x: newDateString(5),
    y: 21,
  },
  {
    x: newDateString(7),
    y: 12,
  },
  {
    x: newDateString(15),
    y: 38,
  },
];

/*...*/
<Line
  options={options}
  data={{
     datasets: [{ data: data }],
       labels: labels,
     }}
/>
</code>```

I got the following result (not even close from sample)

Thanks you

答: Your problem is in your options, the scale configs never get applied since you defined the options for the scales in the scale key while they have to be defined in the scales key, note the extra s

Title: Chartjs sample can't be reproduced

Body:
I am looking to reproduce the result of this sample from Chartjs doc :
https://www.chartjs.org/docs/latest/samples/scales/time-line.html

What I am looking for is the scale result on x :

I use react with react-chartjs-2 and a simplified version of the example, but I managed to keep same config and data for the x axis :

import { DateTime } from 'luxon';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS, registerables } from 'chart.js';
import 'chartjs-adapter-luxon';

ChartJS.register(...registerables);

function newDate(days: number) {
  return DateTime.now().plus({ days }).toJSDate();
}

function newDateString(days: number) {
  return DateTime.now().plus({ days }).toISO();
}

const options = {
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: { display: false },
  },
  scale: {
    x: {
      type: 'time',
      time: {
        tooltipFormat: 'DD T',
      },
    },
    y: {
      type: 'linear',
      suggestedMin: 0,
      suggestedMax: 100,
      ticks: {
        stepSize: 20,
      },
    },
  },
};

const labels = [newDate(0), newDate(1), newDate(2), newDate(3), newDate(4), newDate(5), newDate(6)];
const Data = [
  {
    x: newDateString(0),
    y: 41,
  },
  {
    x: newDateString(5),
    y: 21,
  },
  {
    x: newDateString(7),
    y: 12,
  },
  {
    x: newDateString(15),
    y: 38,
  },
];

/*...*/
<Line
  options={options}
  data={{
     datasets: [{ data: data }],
       labels: labels,
     }}
/>

I got the following result (not even close from sample)

Thanks you


问:
How do I port code for Borland C++ builder to Linux?
I have source code for a Windows DLL that is written in C++ and uses Visual Component Library. Now my task is to port that to Linux, but I don't have source code for the VCL itself, or any kind of documentation (and I have never worked with Borland C++; in my Windows days I used MFC).

This should not be all that hard, since my DLL does not have any GUI: as far as I can see, it mostly uses VCL for multithreading. I ran into a class that inherits from TThread and that is where I got stuck. I did some search on the Internet, but found no documentation for VCL so far. I would like to avoid buying a book on Borland C++ Builder, because I don't have time to wait for it to arrive from the Amazon. I cannot consider buying the package for Windows, because at work I only have a Linux box.

Any suggestions?

答:
You can download their free compiler and try experimenting with it. It should be possible to run it under WINE at least. Maybe even under FreeDOS.

It should be related to the TThread class in Delphi/Kylix. That is another alternative for exploring it. I do believe that the most important methods were run() and sync() but it's been ages since I used it.

However, if you plan to cleanly port the code to Linux, it may help to re-implement the TThread class yourself, using some boost libraries or something.

OwnerDisplayName: ajanicij

ContentLicense: CC BY-SA 2.5

OwnerDisplayName: sybreon


问:
How to handle the more than two images in the tableview?
Iam developing one application.In that i use the 4 rows for table view.Each row contain the imageview.Every imageview canget the image from CAMERA.My problem is after getting the third image,images will be appear at different positions.ANd if u scroll the tableviewthen imageviews will got the black color.Images not appeared.Please tell me how to solve this one.Is this memory problem or not.please tell me.</p>

答:
I had a similar issue, if I understand you correctly.  If you are using dequeueReusableCellWithIdentifier to get your cells (which you should do) then you will need to set the values of all properties of the cell or you will have garbage left over from previous cells.

For example:

```<code>cell.detailedTextLabel.text = @"";
</code>```

If this particular cell has no detailedText.  As @Akshay says you need to post your cellForRow code so we can see what is going on.

Body:
I had a similar issue, if I understand you correctly.  If you are using dequeueReusableCellWithIdentifier to get your cells (which you should do) then you will need to set the values of all properties of the cell or you will have garbage left over from previous cells.

For example:

cell.detailedTextLabel.text = @"";

If this particular cell has no detailedText.  As @Akshay says you need to post your cellForRow code so we can see what is going on.


问:
Append results from a shell command to a list in Python
I wrote a shell command inside Python to collect the IPv4 address in a server.

```<code># cat ipv4.py
#!/usr/bin/env python3
import os
ipv4_regex = r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
os_cmd = f"ip a s eth0 | egrep -o 'inet {ipv4_regex}' | cut -d' ' -f2"
os.system(os_cmd)
</code>```

Output:

```<code># ./ipv4.py
192.168.0.2
192.168.0.3
192.168.0.4
</code>```

How do I append each IPv4 address from the above output to a list in Python?.

答:
This should do the trick:

import subprocess
x = subprocess.check_output(['os_cmd'])
```

Body:
I wrote a shell command inside Python to collect the IPv4 address in a server.

# cat ipv4.py
#!/usr/bin/env python3
import os
ipv4_regex = r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
os_cmd = f"ip a s eth0 | egrep -o 'inet {ipv4_regex}' | cut -d' ' -f2"
os.system(os_cmd)

Output:

# ./ipv4.py
192.168.0.2
192.168.0.3
192.168.0.4

How do I append each IPv4 address from the above output to a list in Python?.


问:
React Js: Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
I want to fetch my Json file in react js, for this I am using fetch. But it shows an error

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

What could be the error, i am getting no clue. I even validated my JSON.

```<code>handleGetJson(){
  console.log("inside handleGetJson");
  fetch(`./fr.json`)
    .then((response) => response.json())
    .then((messages) => {console.log("messages");});
}
</code>```

My Json (fr.json)

```<code>{
  "greeting1": "(fr)choose an emoticon",
  "addPhoto1": "(fr)add photo",
  "close1": "(fr)close"
}
</code>```

答:
Add "method: 'GET'"</p>
```<code>let query = {
      method: 'GET',
      headers: {
        authToken: token,
        "Content-Type": "application/json",
    },
 };
</code>```

Body:
I want to fetch my Json file in react js, for this I am using fetch. But it shows an error

Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

What could be the error, i am getting no clue. I even validated my JSON.

handleGetJson(){
  console.log("inside handleGetJson");
  fetch(`./fr.json`)
    .then((response) => response.json())
    .then((messages) => {console.log("messages");});
}

My Json (fr.json)

{
  "greeting1": "(fr)choose an emoticon",
  "addPhoto1": "(fr)add photo",
  "close1": "(fr)close"
}

Body:
Add "method: 'GET'"

let query = {
      method: 'GET',
      headers: {
        authToken: token,
        "Content-Type": "application/json",
    },
 };


问:
How to count sequential repeats of a value (allowing for one skip)
I am trying to produce a variable that counts how many times a "1" appeared sequentially in the preceding rows for a different variable. However, I need the count to persist even if there is one row missing a 1. (i.e., 10111011 should register as an 8). The code I use to count sequential 1s is:

The following code provides an example of the kind of thing I'm trying to do:

```<code>input <- c(1,0,1,1,0,1,1,0,1,0,1)
dfseq <- data.frame(input)
dfseq$seq <- sequence(rle(as.character(dfseq$input))$lengths)
</code>```

which produces the following dataframe:

```<code>data_struc <-
  structure(list(
    input = c(1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1),
    seq = c(1L,
            1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L)
  ),
  row.names = c(NA,-11L),
  class = "data.frame")
</code>```

However, I want the sequence to allow for one row of "failure" on the sequence, such that it continues to count consecutive ones even if one row contains a 0 and then the 1s continue. It should only stop counting once two 0s appear consecutively

答:
You were on the right track using rle. Using an extended dataset to illustrate the "allowing" part

```<code>rle_obj <- rle(dfseq$input)

sum(dfseq$input) + sum(ifelse(rle_obj$lengths[rle_obj$values==0]==1,1,0))
[1] 12
</code>```

Data

```<code>dfseq <- structure(list(input = c(1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0,
0, 1), seq = c(1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1)), row.names = c(NA,
-14L), class = "data.frame")

dfseq
   input seq
1      1   1
2      0   1
3      1   1
4      1   2
5      0   1
6      1   1
7      1   2
8      0   1
9      1   1
10     0   1
11     1   1
12     0   1
13     0   2
14     1   1
</code>```

Body:
I am trying to produce a variable that counts how many times a "1" appeared sequentially in the preceding rows for a different variable. However, I need the count to persist even if there is one row missing a 1. (i.e., 10111011 should register as an 8). The code I use to count sequential 1s is:

The following code provides an example of the kind of thing I'm trying to do:

input <- c(1,0,1,1,0,1,1,0,1,0,1)
dfseq <- data.frame(input)
dfseq$seq <- sequence(rle(as.character(dfseq$input))$lengths)

which produces the following dataframe:

data_struc <-
  structure(list(
    input = c(1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1),
    seq = c(1L,
            1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 1L)
  ),
  row.names = c(NA,-11L),
  class = "data.frame")

However, I want the sequence to allow for one row of "failure" on the sequence, such that it continues to count consecutive ones even if one row contains a 0 and then the 1s continue. It should only stop counting once two 0s appear consecutively

Body:
You were on the right track using rle. Using an extended dataset to illustrate the "allowing" part

rle_obj <- rle(dfseq$input)

sum(dfseq$input) + sum(ifelse(rle_obj$lengths[rle_obj$values==0]==1,1,0))
[1] 12

Data

dfseq <- structure(list(input = c(1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0,
0, 1), seq = c(1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1)), row.names = c(NA,
-14L), class = "data.frame")

dfseq
   input seq
1      1   1
2      0   1
3      1   1
4      1   2
5      0   1
6      1   1
7      1   2
8      0   1
9      1   1
10     0   1
11     1   1
12     0   1
13     0   2
14     1   1


问:
Is it possible to define function that creates an N-dimensional list of lists easily?
I have searched and found these questions: How to create a multi-dimensional list and N dimensional array in python which hint toward what I am looking for, but they seem to only make 2D arrays and not ND arrays.

Problem:

My problem is that I am able to create an n-dimensional list of lists for a known n, but I am not sure how it can be generalized to work with all values of n.

Consider this example:

```<code>def makeList(n):
    return [[[n for _ in range(n)]
                for _ in range(n)]
                for _ in range(n)]
print(makeList(3))
</code>```

Output:

```<code>[[[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]],
 [[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]],
 [[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]]]
</code>```

This will create a list of lists that is a 3x3x3 array of 3's which is the intended result, but if we use a different n:

```<code>print(makeList(2))
</code>```

Output:

```<code>[[[2, 2],
  [2, 2]],
 [[2, 2],
  [2, 2]]]
</code>```

This will create a list of lists that is a 2x2x0 array of 2's and this is not the intended result. Instead the results should be a list of lists that is a 2x2 array of 2's.

Likewise if we set n = 4:

```<code>print(makeList(4))
</code>```

This will give a list of lists that is 4x4x4 when it should give a 4x4x4x4 list of lists.

The main issue is that the number of for loops must change depending on the input, but obviously the code can't "come to life" and recode itself magically, hence my issue.

I am looking for a way to get this result that is simple. I am sure I could continue developing ideas for solutions, but I have not been able to think of anything that is concise.

What I have tried:

The first idea I thought of was to use recursion, and this my simple approach:

```<code>def makeList(n, output = []):
    if not output:
        output = [n for _ in range(n)]
    else:
        output = [output for _ in range(n)]
    if len(output) == n:
        return output
    else:
        return makeList(n, output)
</code>```

This obviously will not work because if len(output) == n: will execute the first iteration since the length of the inner loops is equal to the length of the outermost loop. However, even if there was a condition that properly terminated the function, this solution would still not be ideal because I could run into maximum recursion errors with large values of n. Furthermore, even if these issues were resolved this code is still quite long as well as time consuming.

The other potential perspective I considered (and the solution that I found that works) is using a dict. My solution saves the intermediate lists of lists in a dict so it can be used for the next iteration:

```<code>def makeList(n):
    d = {str(i): None for i in range(n)}
    for i in range(n):
        if i == 0:
            d[str(i)] = [n for _ in range(n)]
        else:
            d[str(i)] = [d[str(i-1)] for _ in range(n)]
    return d[str(n-1)]
</code>```

But again, this is very long and doesn't seem very pythonic.

Solution requirements:

The ideal solution would be much more concise than mine with an efficient time complexity that only uses built-in functions.

Other options that are close to these requirements would also be helpful as long as the spirit of the answer is trying to best meet the requirements.

Being concise is the most important aspect, however, which is why I am not fully happy with my current attempts.

答:
Using python support for pattern matching

def nlist(shape: tuple[int, ...], fill_with=None):
    match shape:
        case (n,):
            return [fill_with] * n
        case (n, *rest):
            return [nlist(rest, fill_with) for _ in range(n)]
        case _:
            raise ValueError(f'Invalid value shape={shape}')

def makeList(n):
    return nlist((n,)*n, n)
```

Body:
I have searched and found these questions: How to create a multi-dimensional list and N dimensional array in python which hint toward what I am looking for, but they seem to only make 2D arrays and not ND arrays.

Problem:

My problem is that I am able to create an n-dimensional list of lists for a known n, but I am not sure how it can be generalized to work with all values of n.

Consider this example:

def makeList(n):
    return [[[n for _ in range(n)]
                for _ in range(n)]
                for _ in range(n)]
print(makeList(3))

Output:

[[[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]],
 [[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]],
 [[3, 3, 3],
  [3, 3, 3],
  [3, 3, 3]]]

This will create a list of lists that is a 3x3x3 array of 3's which is the intended result, but if we use a different n:

print(makeList(2))

Output:

[[[2, 2],
  [2, 2]],
 [[2, 2],
  [2, 2]]]

This will create a list of lists that is a 2x2x0 array of 2's and this is not the intended result. Instead the results should be a list of lists that is a 2x2 array of 2's.

Likewise if we set n = 4:

print(makeList(4))

This will give a list of lists that is 4x4x4 when it should give a 4x4x4x4 list of lists.

The main issue is that the number of for loops must change depending on the input, but obviously the code can't "come to life" and recode itself magically, hence my issue.

I am looking for a way to get this result that is simple. I am sure I could continue developing ideas for solutions, but I have not been able to think of anything that is concise.

What I have tried:

The first idea I thought of was to use recursion, and this my simple approach:

def makeList(n, output = []):
    if not output:
        output = [n for _ in range(n)]
    else:
        output = [output for _ in range(n)]
    if len(output) == n:
        return output
    else:
        return makeList(n, output)

This obviously will not work because if len(output) == n: will execute the first iteration since the length of the inner loops is equal to the length of the outermost loop. However, even if there was a condition that properly terminated the function, this solution would still not be ideal because I could run into maximum recursion errors with large values of n. Furthermore, even if these issues were resolved this code is still quite long as well as time consuming.

The other potential perspective I considered (and the solution that I found that works) is using a dict. My solution saves the intermediate lists of lists in a dict so it can be used for the next iteration:

def makeList(n):
    d = {str(i): None for i in range(n)}
    for i in range(n):
        if i == 0:
            d[str(i)] = [n for _ in range(n)]
        else:
            d[str(i)] = [d[str(i-1)] for _ in range(n)]
    return d[str(n-1)]

But again, this is very long and doesn't seem very pythonic.

Solution requirements:

The ideal solution would be much more concise than mine with an efficient time complexity that only uses built-in functions.

Other options that are close to these requirements would also be helpful as long as the spirit of the answer is trying to best meet the requirements.

Being concise is the most important aspect, however, which is why I am not fully happy with my current attempts.


问:
'Method Not Allowed: The method is not allowed for the requested URL.' when submitting text entry
I am running flask python along with HTML, and the problem is simple:

It gives me error 405: Method Not Allowed: The method is not allowed for the requested URL. I have looked this up and people say to include methods=['GET', 'POST'] in the page route, but I already have this.

Python code:

```<code>@app.route('/')
@app.route('/home/', methods=['GET', 'POST'])
def home():
    global count
    guess = request.form.get('guess')
    result, valid = guess_word(guess, word, words)
    print(result, valid)
    try:
            guesses[count-1][2] = 'p'
    except:
            guesses[count-1][2] = ''
    if count < 6:
        if valid:
            guesses[count][0] = guess
            guesses[count][1] = result
    session['guesses'] = guesses
    if valid:
        count += 1
    return render_template('index.html', guesses=session['guesses'])
</code>```

HTML code:

```<code><div class="container2">
    <form method="post">
        <input type="text" placeholder="Guess" class="text-input" name="guess">
    </form>
</div>
</code>```

This worked before, and I changed (what I thought was) nothing, but it suddenly stopped working. It gives me the error when I submit the text entry.

答:
Your form has no action attribute i.e. you have not explicitly said where your data should go to when you submit your form. In the absence of an action attribute, it will assume your home page which is / and from your routing, this does not support POST.

2 possible solutions

Add the action attribute to your form

```<code><form action ="home" method ="post">
</code>```

Keep your data as is and add support for POST to your route for / i.e. change your routing code to

```<code>@app.route('/', methods=['GET', 'POST'])
@app.route('/home/', methods=['GET', 'POST'])
</code>```

Body:
I am running flask python along with HTML, and the problem is simple:

It gives me error 405: Method Not Allowed: The method is not allowed for the requested URL. I have looked this up and people say to include methods=['GET', 'POST'] in the page route, but I already have this.

Python code:

@app.route('/')
@app.route('/home/', methods=['GET', 'POST'])
def home():
    global count
    guess = request.form.get('guess')
    result, valid = guess_word(guess, word, words)
    print(result, valid)
    try:
            guesses[count-1][2] = 'p'
    except:
            guesses[count-1][2] = ''
    if count < 6:
        if valid:
            guesses[count][0] = guess
            guesses[count][1] = result
    session['guesses'] = guesses
    if valid:
        count += 1
    return render_template('index.html', guesses=session['guesses'])

HTML code:

    <form method="post">
        <input type="text" placeholder="Guess" class="text-input" name="guess">
    </form>

This worked before, and I changed (what I thought was) nothing, but it suddenly stopped working. It gives me the error when I submit the text entry.

Body:
Your form has no action attribute i.e. you have not explicitly said where your data should go to when you submit your form. In the absence of an action attribute, it will assume your home page which is / and from your routing, this does not support POST.

2 possible solutions

Add the action attribute to your form

<form action ="home" method ="post">

Keep your data as is and add support for POST to your route for / i.e. change your routing code to

@app.route('/', methods=['GET', 'POST'])
@app.route('/home/', methods=['GET', 'POST'])


问:
Is there any way to optimise this code?
I have a piece of code which will invert all the checkboxes on my form. I have multiple elements (not just checkboxes but also  <input type='text'>'s) in it. The reason I need it to be optimised is because it takes about two to three seconds to select all the checkboxes (275 right now).

Here's my code:

```<code>function FormInverse() {
    var iCheckbox = 1; // Because there are multiple input elements, we need to distinquish the input element ID and the row id
    var FormLength = document.FormFacturen.elements.length;
    for (i=0; i < FormLength; i++) {
        var FormElementType = document.FormFacturen.elements[i].type;
        if (FormElementType == "checkbox") {
            var Elements = document.getElementsByClassName('row' + iCheckbox); // Alle elementen in de array zetten
            var iNumElements = Elements.length;
            for (iElement=0; iElement < iNumElements; iElement++) {
                if (document.FormFacturen[i].checked == true) {
                    Elements[iElement].className = "invoice-tr-standard row" + iCheckbox;
                } else {
                    Elements[iElement].className = "invoice-tr-clicked row" + iCheckbox;
                }
            }
            iCheckbox++;
            document.FormFacturen[i].checked = !document.FormFacturen[i].checked;
        }
    }
}
</code>```

And here is the document.getElementsByClassName function:

```<code>document.getElementsByClassName = function(cl) {
    var retnode = [];
    var myclass = new RegExp('\\b'+cl+'\\b');
    var elem = document.getElementsByTagName('*');
    for (var i = 0; i < elem.length; i++) {
        var classes = elem[i].className;
        if (myclass.test(classes)) retnode.push(elem[i]);
    }
    return retnode;
};
</code>```

答:
You should look into a library like JQuery.  It will handle this kind of thing well.

There are a lot of little things you can do to improve your code though.  First thing I notice is that your getElementsByClassName function is looping through ALL elements on your page every time you call it.  You could change this line:

```<code>var elem = document.getElementsByTagName('*');
</code>```

to just get the input elements:

```<code>var elem = document.getElementsByTagName('input');
</code>```

Title: Is there any way to optimise this code?

Body:
I have a piece of code which will invert all the checkboxes on my form. I have multiple elements (not just checkboxes but also  <input type='text'>'s) in it. The reason I need it to be optimised is because it takes about two to three seconds to select all the checkboxes (275 right now).

Here's my code:

function FormInverse() {
    var iCheckbox = 1; // Because there are multiple input elements, we need to distinquish the input element ID and the row id
    var FormLength = document.FormFacturen.elements.length;
    for (i=0; i < FormLength; i++) {
        var FormElementType = document.FormFacturen.elements[i].type;
        if (FormElementType == "checkbox") {
            var Elements = document.getElementsByClassName('row' + iCheckbox); // Alle elementen in de array zetten
            var iNumElements = Elements.length;
            for (iElement=0; iElement < iNumElements; iElement++) {
                if (document.FormFacturen[i].checked == true) {
                    Elements[iElement].className = "invoice-tr-standard row" + iCheckbox;
                } else {
                    Elements[iElement].className = "invoice-tr-clicked row" + iCheckbox;
                }
            }
            iCheckbox++;
            document.FormFacturen[i].checked = !document.FormFacturen[i].checked;
        }
    }
}

And here is the document.getElementsByClassName function:

document.getElementsByClassName = function(cl) {
    var retnode = [];
    var myclass = new RegExp('\\b'+cl+'\\b');
    var elem = document.getElementsByTagName('*');
    for (var i = 0; i < elem.length; i++) {
        var classes = elem[i].className;
        if (myclass.test(classes)) retnode.push(elem[i]);
    }
    return retnode;
};

Body:
You should look into a library like JQuery.  It will handle this kind of thing well.

There are a lot of little things you can do to improve your code though.  First thing I notice is that your getElementsByClassName function is looping through ALL elements on your page every time you call it.  You could change this line:

var elem = document.getElementsByTagName('*');

to just get the input elements:

var elem = document.getElementsByTagName('input');


问:
numpy.array() is not converting tiff image to 2D array
I have been trying to figure out why the numpy.array() method is converting my tiff image into an object (dtype=object). I tried this with other tiff images and I did not encounter this problem. I am pretty sure it has to do something with how my "actin2.tif" image is acquired. I just need to be able to convert this particular tiff image to a 2D array. This is what my code looks like:

```<code>>>> import numpy
>>> from PIL import Image
>>> a = Image.open('actin2.tif')
>>> a_array = numpy.array(a)
>>> a
<PIL.TiffImagePlugin.TiffImageFile image mode=I;16B size=37x58 at 0x14BBC68>
>>> a_array
array(<PIL.TiffImagePlugin.TiffImageFile image mode=I;16B size=37x58 at 0x14BBC68>, dtype=object)
</code>```

I eventually need to be able to manipulate the value of the pixels in the image and I cannot do that without the image being converted to a 2D array. Currently, this is the error thrown when I try to manipulate the array:

```<code>structure_masked = numpy.multiply(structure_mask,image)
TypeError: unsupported operand type(s) for *: 'bool' and 'instance'
</code>```

which is a result from this line of code:

```<code>structure_masked = numpy.multiply(structure_mask,image)
</code>```

"structure_mask" and "image" were converted to numpy arrays in the same way as mentioned above.

I have tried changing mode and dtype but that does not seem to be working, any suggestions?

答:
```<code>>>> a = Image.open('actin2.tif')
>>> a_array = numpy.array(a)
>>> a # you are printing the image not array.
</code>```

you are printing image instead of array. It should be >>>a_array
instead of >>>a

Body:
I have been trying to figure out why the numpy.array() method is converting my tiff image into an object (dtype=object). I tried this with other tiff images and I did not encounter this problem. I am pretty sure it has to do something with how my "actin2.tif" image is acquired. I just need to be able to convert this particular tiff image to a 2D array. This is what my code looks like:

>>> import numpy
>>> from PIL import Image
>>> a = Image.open('actin2.tif')
>>> a_array = numpy.array(a)
>>> a
<PIL.TiffImagePlugin.TiffImageFile image mode=I;16B size=37x58 at 0x14BBC68>
>>> a_array
array(<PIL.TiffImagePlugin.TiffImageFile image mode=I;16B size=37x58 at 0x14BBC68>, dtype=object)

I eventually need to be able to manipulate the value of the pixels in the image and I cannot do that without the image being converted to a 2D array. Currently, this is the error thrown when I try to manipulate the array:

structure_masked = numpy.multiply(structure_mask,image)
TypeError: unsupported operand type(s) for *: 'bool' and 'instance'

which is a result from this line of code:

structure_masked = numpy.multiply(structure_mask,image)

"structure_mask" and "image" were converted to numpy arrays in the same way as mentioned above.

I have tried changing mode and dtype but that does not seem to be working, any suggestions?

Body:
>>> a = Image.open('actin2.tif')
>>> a_array = numpy.array(a)
>>> a # you are printing the image not array.

you are printing image instead of array. It should be >>>a_array
instead of >>>a


问:
Flutter Windows option not showing
I'm trying to run my old project on Windows Debug Mode.(Released couple of days ago).
I updated my flutter version to 2.10 using flutter upgrade and I did flutter doctor .
Everything is fine but I can't find Windows in my debug option.
Is it because I'm using macOS ?
I just want to test how my app will behave or look on Windows before building the final release.

答:
Yes, that's the problem. You need to be on Windows to build for Windows.
Check here, the second note from the top (unless they changed something with the new release).</p>

Title: Flutter Windows option not showing


问:
How to lookup object in array with aggregation in MongoDB?
I'm using aggregate([...]) method to select documents from MongoDB, but I have a problem with $lookup, I can't get the results of the reference field info after query, it not works because it always return empty array. How can i solve this problem ?

My MongoSchema config:

```<code>const PostModel = new Schema({
  ...,
  info: [
    {
      label: {
        type: ObjectId,
        ref: 'catalogs',
        required: true
      },
      value: {
        type: ObjectId,
        ref: 'attributes',
        required: true
      }
    }
  ],
  ...
})
</code>```

My code for execute aggregate to query collection:

```<code>  const doc = await PostModel.aggregate([
    {
      "$lookup": {
        "from": "catalogs",
        "localField": "info.label",
        "foreignField": "_id",
        "as": "infoLabel"
      }
    },
    {
      "$lookup": {
        "from": "attributes",
        "localField": "info.value",
        "foreignField": "_id",
        "as": "infoValue"
      }
    },
    {
      "$project": {
        info: {
          label: '$infoLabel',
          value: '$infoValue'
        }
      }
    }
  ])

  console.log(doc) // it always return empty array :(
</code>```

答:
You need to first unwind the info then use lookup query that will work</p>
```<code>{ $unwind:"$info" },
{ $lookup:{ ... } }
</code>```

Body:
I'm using aggregate([...]) method to select documents from MongoDB, but I have a problem with $lookup, I can't get the results of the reference field info after query, it not works because it always return empty array. How can i solve this problem ?

My MongoSchema config:

const PostModel = new Schema({
  ...,
  info: [
    {
      label: {
        type: ObjectId,
        ref: 'catalogs',
        required: true
      },
      value: {
        type: ObjectId,
        ref: 'attributes',
        required: true
      }
    }
  ],
  ...
})

My code for execute aggregate to query collection:

  const doc = await PostModel.aggregate([
    {
      "$lookup": {
        "from": "catalogs",
        "localField": "info.label",
        "foreignField": "_id",
        "as": "infoLabel"
      }
    },
    {
      "$lookup": {
        "from": "attributes",
        "localField": "info.value",
        "foreignField": "_id",
        "as": "infoValue"
      }
    },
    {
      "$project": {
        info: {
          label: '$infoLabel',
          value: '$infoValue'
        }
      }
    }
  ])

  console.log(doc) // it always return empty array :(

Body:
You need to first unwind the info then use lookup query that will work

{ $unwind:"$info" },
{ $lookup:{ ... } }


问:
Importing Json directly into class
I want to import  Json file into a class

This is a toy Json file I have

```<code>{
    "a": {
        "Name": "foo",
        "Age": 2
    },
    "b": {
        "Name": "bar",
        "Age": 3
    }
}
</code>```

I import the Json files inside the class Params using the following code.
Then I use this information to create two persons, a and b

```<code>public class Params
{
    JObject m_params;

    Params()
    {
        using (StreamReader file = File.OpenText(filename))
        using (JsonTextReader reader = new JsonTextReader(file))
        {
            m_params = (JObject)JToken.ReadFrom(reader);
        }
        Person Person1 = new Person(m_params["a"]);
        Person Person2 = new Person(m_params["b"]);
    }
}
</code>```

Now here's the implementation of Person

```<code>public class Person
{
    string Name;
    int Age;
    Person(JToken data)
    {
        Name = data["Name"];
        Age = data["Age"];
    }
}
</code>```

This works, but I feel it should be an easier way to do that.

If instead of just having name and age I have 100 parameters, the initialization of Person will be 100 lines of code.

If there a way of directly assigning data["Name"] to Person.Name and do the rest for all the parameters of Person?

How could my importing be improved, so when I have a lot of people with a lot of fields I can import everything easily?

答:
You can simply deserialize the objects directly like this:</p>
```<code>public class Params
{
    Person a;
    Person b;
}

public class Person
{
    string Name;
    int Age;
}

var jsonText = File.ReadAllText("config.json");
var people = JsonSerializer.Deserialize<Params>(jsonText);
</code>```

Title: Importing Json directly into class

Body:
I want to import  Json file into a class

This is a toy Json file I have

{
    "a": {
        "Name": "foo",
        "Age": 2
    },
    "b": {
        "Name": "bar",
        "Age": 3
    }
}

I import the Json files inside the class Params using the following code.
Then I use this information to create two persons, a and b

public class Params
{
    JObject m_params;

    Params()
    {
        using (StreamReader file = File.OpenText(filename))
        using (JsonTextReader reader = new JsonTextReader(file))
        {
            m_params = (JObject)JToken.ReadFrom(reader);
        }
        Person Person1 = new Person(m_params["a"]);
        Person Person2 = new Person(m_params["b"]);
    }
}

Now here's the implementation of Person

public class Person
{
    string Name;
    int Age;
    Person(JToken data)
    {
        Name = data["Name"];
        Age = data["Age"];
    }
}

This works, but I feel it should be an easier way to do that.

If instead of just having name and age I have 100 parameters, the initialization of Person will be 100 lines of code.

If there a way of directly assigning data["Name"] to Person.Name and do the rest for all the parameters of Person?

How could my importing be improved, so when I have a lot of people with a lot of fields I can import everything easily?

Body:
You can simply deserialize the objects directly like this:

public class Params
{
    Person a;
    Person b;
}

public class Person
{
    string Name;
    int Age;
}

var jsonText = File.ReadAllText("config.json");
var people = JsonSerializer.Deserialize<Params>(jsonText);


问:
How to generate a random Vector3 point inside a polygon
I work on Unity3D and I have a Vector3 array, this array is the vertex of a polygon.
Now I try to Generate a random point inside the polygon and I don't know how many vertex I have.

e.g:

```<code>polygonBorders = new Vector3[3];

        polygonBorders[0] = new Vector3(35.3f, 1.3f, -20.1f);
        polygonBorders[1] = new Vector3(35.3f, 1.3f, -3.42f);
        polygonBorders[2] = new Vector3(52.11f, 1.3f, -3.42f);
</code>```

this is my polygon and I want a method like that:

```<code> Vector3 GeneratePointInsidePolygon(Vector3[] polyogn, Vector3 point)
</code>```

I try to find a solution all over the Internet and there is no solution or libraey

答:
I find a nice way to do that with the next snippet:

```<code>private Vector3 GeneratePointInsidePolygon(List<Vector3> polygon)
{
    Vector3 MinVec = MinPointOnThePolygon(polygon);
    Vector3 MaxVec = MaxPointOnThePolygon(polygon);
    Vector3 GenVector;

    float x = ((Random.value) * (MaxVec.x- MinVec.x)) + MinVec.x;
    float z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
    GenVector = new Vector3(x, groundHight, z);

    while(!InConfinedSpace.IsPointInPolygon(polygon,GenVector))
    {
        x = ((Random.value) * (MaxVec.x - MinVec.x)) + MinVec.x;
        z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
        GenVector.x = x;
        GenVector.z = z;
    }
    return GenVector;

}

private Vector3 MinPointOnThePolygon(List<Vector3> polygon)
{
    float minX = polygon[0].x;
    float minZ = polygon[0].z;
    for (int i = 1; i<polygon.Count;i++)
    {
        if(minX > polygon[i].x)
        {
            minX = polygon[i].x;
        }
        if (minZ > polygon[i].z)
        {
            minZ = polygon[i].z;
        }
    }
    return new Vector3(minX, groundHight, minZ);
}

private Vector3 MaxPointOnThePolygon(List<Vector3> polygon)
{
    float maxX = polygon[0].x;
    float maxZ = polygon[0].z;
    for (int i = 1; i < polygon.Count; i++)
    {
        if (maxX < polygon[i].x)
        {
            maxX = polygon[i].x;
        }
        if (maxZ < polygon[i].z)
        {
            maxZ = polygon[i].z;
        }
    }
    return new Vector3(maxX, groundHight, maxZ);
}

private bool IsPointInPolygon(List<Vector3> polygon, Vector3 point)
{
    bool isInside = false;
    for (int i = 0, j = polygon.Count - 1; i < polygon.Count; j = i++)
    {
        if (((polygon[i].x > point.x) != (polygon[j].x > point.x)) &&
        (point.z < (polygon[j].z - polygon[i].z) * (point.x - polygon[i].x) / (polygon[j].x - polygon[i].x) + polygon[i].z))
        {
            isInside = !isInside;
        }
    }
    return isInside;
}
</code>```

The snippet finds the minimum and maximum polygon vertex and then generates a random number inside and checks if the point is inside the polygon every time, if it's not it generates another point.

Body:
I work on Unity3D and I have a Vector3 array, this array is the vertex of a polygon.
Now I try to Generate a random point inside the polygon and I don't know how many vertex I have.

e.g:

polygonBorders = new Vector3[3];

        polygonBorders[0] = new Vector3(35.3f, 1.3f, -20.1f);
        polygonBorders[1] = new Vector3(35.3f, 1.3f, -3.42f);
        polygonBorders[2] = new Vector3(52.11f, 1.3f, -3.42f);

this is my polygon and I want a method like that:

 Vector3 GeneratePointInsidePolygon(Vector3[] polyogn, Vector3 point)

I try to find a solution all over the Internet and there is no solution or libraey

Body:
I find a nice way to do that with the next snippet:

private Vector3 GeneratePointInsidePolygon(List<Vector3> polygon)
{
    Vector3 MinVec = MinPointOnThePolygon(polygon);
    Vector3 MaxVec = MaxPointOnThePolygon(polygon);
    Vector3 GenVector;

    float x = ((Random.value) * (MaxVec.x- MinVec.x)) + MinVec.x;
    float z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
    GenVector = new Vector3(x, groundHight, z);

    while(!InConfinedSpace.IsPointInPolygon(polygon,GenVector))
    {
        x = ((Random.value) * (MaxVec.x - MinVec.x)) + MinVec.x;
        z = ((Random.value) * (MaxVec.z - MinVec.z)) + MinVec.z;
        GenVector.x = x;
        GenVector.z = z;
    }
    return GenVector;

}

private Vector3 MinPointOnThePolygon(List<Vector3> polygon)
{
    float minX = polygon[0].x;
    float minZ = polygon[0].z;
    for (int i = 1; i<polygon.Count;i++)
    {
        if(minX > polygon[i].x)
        {
            minX = polygon[i].x;
        }
        if (minZ > polygon[i].z)
        {
            minZ = polygon[i].z;
        }
    }
    return new Vector3(minX, groundHight, minZ);
}

private Vector3 MaxPointOnThePolygon(List<Vector3> polygon)
{
    float maxX = polygon[0].x;
    float maxZ = polygon[0].z;
    for (int i = 1; i < polygon.Count; i++)
    {
        if (maxX < polygon[i].x)
        {
            maxX = polygon[i].x;
        }
        if (maxZ < polygon[i].z)
        {
            maxZ = polygon[i].z;
        }
    }
    return new Vector3(maxX, groundHight, maxZ);
}

private bool IsPointInPolygon(List<Vector3> polygon, Vector3 point)
{
    bool isInside = false;
    for (int i = 0, j = polygon.Count - 1; i < polygon.Count; j = i++)
    {
        if (((polygon[i].x > point.x) != (polygon[j].x > point.x)) &&
        (point.z < (polygon[j].z - polygon[i].z) * (point.x - polygon[i].x) / (polygon[j].x - polygon[i].x) + polygon[i].z))
        {
            isInside = !isInside;
        }
    }
    return isInside;
}

The snippet finds the minimum and maximum polygon vertex and then generates a random number inside and checks if the point is inside the polygon every time, if it's not it generates another point.


问:
How to remove white underline in a SearchView widget in Toolbar Android
I am using the Toolbar search widget in my project. Everything works fine but expect the thing which I am completely stuck up with removing the underline below the search field in my toolbar. I have tried many solutions and nothing works out. Below are some of the solutions that I tried.

Requirement is to remove white underline in the image

Ist Solution:

```<code>//Removing underline

    int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
    View searchPlate = searchView.findViewById(searchPlateId);
    if (searchPlate!=null) {
        searchPlate.setBackgroundColor (Color.TRANSPARENT);
        int searchTextId = searchPlate.getContext ().getResources ().getIdentifier ("android:id/search_src_text", null, null);

    }
</code>```

IInd Solution:

```<code> EditText searchEdit = ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text));
 searchEdit.setBackgroundColor(Color.TRANSPARENT);
</code>```

The above code works to change the background of EditText but still underline is displaying below the close icon in SearchBar.

Complete code that I am using for SearchBar widget as follows:

```<code>    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater infl) {
        super.onCreateOptionsMenu(menu, infl);
        MenuInflater inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.action_search, menu);
        final SearchView searchView = (SearchView) MenuItemCompat
                .getActionView(menu.findItem(R.id.search));

        SearchManager searchManager = (SearchManager) getActivity ().getSystemService (getActivity ().SEARCH_SERVICE);
        searchView.setSearchableInfo (searchManager.getSearchableInfo (getActivity ().getComponentName ()));

        //changing edittext color
        EditText searchEdit = ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text));
        searchEdit.setTextColor(Color.WHITE);
}
</code>```

action_search.xml

```<code><?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:compat="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/search"
        android:title="Search"
        android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
        compat:showAsAction="ifRoom|collapseActionView"
        compat:actionViewClass="android.support.v7.widget.SearchView" />
</menu>
</code>```

possible duplicate of this

答:
if you want to remove the underline from SearchView, then just copy paste the below code to your SearchView. it works

```<code> android:queryBackground="@null"
</code>```

like this,

```<code>      <SearchView
                android:id="@+id/searchView"
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:queryBackground="@null"
                />
</code>```

Body:
I am using the Toolbar search widget in my project. Everything works fine but expect the thing which I am completely stuck up with removing the underline below the search field in my toolbar. I have tried many solutions and nothing works out. Below are some of the solutions that I tried.

Requirement is to remove white underline in the image

Ist Solution:

//Removing underline

    int searchPlateId = searchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
    View searchPlate = searchView.findViewById(searchPlateId);
    if (searchPlate!=null) {
        searchPlate.setBackgroundColor (Color.TRANSPARENT);
        int searchTextId = searchPlate.getContext ().getResources ().getIdentifier ("android:id/search_src_text", null, null);

    }

IInd Solution:

 EditText searchEdit = ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text));
 searchEdit.setBackgroundColor(Color.TRANSPARENT);

The above code works to change the background of EditText but still underline is displaying below the close icon in SearchBar.

Complete code that I am using for SearchBar widget as follows:

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater infl) {
        super.onCreateOptionsMenu(menu, infl);
        MenuInflater inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.action_search, menu);
        final SearchView searchView = (SearchView) MenuItemCompat
                .getActionView(menu.findItem(R.id.search));

        SearchManager searchManager = (SearchManager) getActivity ().getSystemService (getActivity ().SEARCH_SERVICE);
        searchView.setSearchableInfo (searchManager.getSearchableInfo (getActivity ().getComponentName ()));

        //changing edittext color
        EditText searchEdit = ((EditText)searchView.findViewById(android.support.v7.appcompat.R.id.search_src_text));
        searchEdit.setTextColor(Color.WHITE);
}

action_search.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:compat="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/search"
        android:title="Search"
        android:icon="@drawable/abc_ic_search_api_mtrl_alpha"
        compat:showAsAction="ifRoom|collapseActionView"
        compat:actionViewClass="android.support.v7.widget.SearchView" />
</menu>

possible duplicate of this

Body:
if you want to remove the underline from SearchView, then just copy paste the below code to your SearchView. it works

 android:queryBackground="@null"

like this,

      <SearchView
                android:id="@+id/searchView"
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:queryBackground="@null"
                />


问:
Delta Query with delta token: Microsoft Graph SDK
I am working on change notifications for users using Microsoft Graph SDK in a .netcore application.
I am using delta query to get the latest changes.

```<code>private static IUserDeltaCollectionPage? lastPage = null;
private async Task<IUserDeltaCollectionPage> GetUsers(GraphServiceClient graphClient, object? deltaLink)
{
  IUserDeltaCollectionPage page;

  if (lastPage == null || deltaLink == null)
  {
    page = await graphClient.Users
                            .Delta()
                            .Request()
                            .GetAsync();
  }
  else
  {
    lastPage.InitializeNextPageRequest(graphClient, deltaLink.ToString());
    page = await lastPage.NextPageRequest.GetAsync();
  }

  lastPage = page;
  return page;
}
</code>```

The problem I am facing with this approach is that, if the application restarts for what ever reason the lastPage will be null. In which case the next time the application runs it will bring back all the users. I don't want to get all the users, I just want to get the changed users.

Is there a way to make a delta query with the latest delta link?

I tried the below but I am getting badly formed query error.

```<code>var queryOptions = new List<QueryOption>()
                    {
                        new QueryOption("$deltatoken", deltaLink?.ToString())
                    };

await graphClient.Users.Delta().Request(options).GetAsync();
</code>```

答:
You can ask for the latest deltaLink by adding $deltaToken=latest to the delta function and the response will contain a deltaLink and no resource data.

Then you need to use received deltaLink

```<code>var queryOptions = new List<QueryOption>()
{
    new QueryOption("$deltatoken", "latest")
};

var page = await graphClient.Groups.Delta().Request(options).GetAsync();
var users = page.CurrentPage.ToList();
if (page.NextPageRequest!=null)
{
    // get latest data
    page = await page.NextPageRequest.GetAsync();
}
</code>```

Resources:

delta query

Body:
I am working on change notifications for users using Microsoft Graph SDK in a .netcore application.
I am using delta query to get the latest changes.

private static IUserDeltaCollectionPage? lastPage = null;
private async Task<IUserDeltaCollectionPage> GetUsers(GraphServiceClient graphClient, object? deltaLink)
{
  IUserDeltaCollectionPage page;

  if (lastPage == null || deltaLink == null)
  {
    page = await graphClient.Users
                            .Delta()
                            .Request()
                            .GetAsync();
  }
  else
  {
    lastPage.InitializeNextPageRequest(graphClient, deltaLink.ToString());
    page = await lastPage.NextPageRequest.GetAsync();
  }

  lastPage = page;
  return page;
}

The problem I am facing with this approach is that, if the application restarts for what ever reason the lastPage will be null. In which case the next time the application runs it will bring back all the users. I don't want to get all the users, I just want to get the changed users.

Is there a way to make a delta query with the latest delta link?

I tried the below but I am getting badly formed query error.

var queryOptions = new List<QueryOption>()
                    {
                        new QueryOption("$deltatoken", deltaLink?.ToString())
                    };

await graphClient.Users.Delta().Request(options).GetAsync();

Body:
You can ask for the latest deltaLink by adding $deltaToken=latest to the delta function and the response will contain a deltaLink and no resource data.

Then you need to use received deltaLink

var queryOptions = new List<QueryOption>()
{
    new QueryOption("$deltatoken", "latest")
};

var page = await graphClient.Groups.Delta().Request(options).GetAsync();
var users = page.CurrentPage.ToList();
if (page.NextPageRequest!=null)
{
    // get latest data
    page = await page.NextPageRequest.GetAsync();
}

Resources:

delta query


问:
How can I get the value in the selected using knockout?
So, I'm getting some problems of how to get the value of the selected option in data-bind with foreach, for example, in the second one select that I have in the code html. How can I get the value of the selected option at the moment?

I tried to follow an example that I had, but I'm failing to make it happen in this one.
In resume, what is the command to get the value of the selected option.

```<code> **HTML**
        <select id="corridas" data-bind="value: selectRace, foreach : races," aria-  label="CORRIDAS">
            <option data-bind="text: Name" ></option>
        </select>
        <select id="nacionalidade" data-bind="value: selectNationality, foreach : nationalities" aria-label="NACIONALIDADES">
            <option data-bind="text:Name"></option>
        </select>

</code>```

JS:

```<code>var vm = function () {
        console.log('ViewModel initiated...');
        //---Variáveis locais
        var self = this;
        self.baseUri = ko.observable('http://192.168.160.58/Formula1/api/drivers');
        self.baseUri1 = ko.observable('http://192.168.160.58/Formula1/api/Nationalities');
        self.baseUri2 = ko.observable('http://192.168.160.58/Formula1/api/Races');
        //Variaveis para drivers
        self.error = ko.observable('');
        self.passingMessage = ko.observable('');
        self.records = ko.observableArray([]);
        self.currentPage = ko.observable(1);
        self.pagesize = ko.observable(10);
        self.totalRecords = ko.observable(50);
        self.hasPrevious = ko.observable(false);
        self.hasNext = ko.observable(false);

        //Variaveis para nacionalidades
        self.selectNationality = ko.observable(null);
        self.nationalities = ko.observableArray([]);
        console.log("Here")
        console.log(self.selectNationality)

        // Funçao para obter a List onde irei buscar toda a informaçao das Nationalities
        self.AllNationalities = function () {
            console.log('CALL: Get NATIONALITIES ...');
            var composedUri1 = self.baseUri1()
            ajaxHelper(composedUri1, 'GET').done(function (data) {
                console.log(self.selectNationality)
                self.nationalities(data.List);
            });
        };

        //Variaveis para corridas
        self.selectRace = ko.observable(null);
        self.races = ko.observableArray([]);

        //Funcao para obter a List onde irei buscar toda a informaçao das Races
        self.AllRaces = function () {
            console.log('CALL: GET RACES...');
            var composedUri2 = self.baseUri2()
            ajaxHelper(composedUri2, 'GET').done(function (data) {
                self.races(data.List);
            });
        }

        //Paginação
        self.previousPage = ko.computed(function () {
            return self.currentPage() * 1 - 1;
        }, self);
        self.nextPage = ko.computed(function () {
            return self.currentPage() * 1 + 1;
        }, self);
        self.fromRecord = ko.computed(function () {
            return self.previousPage() * self.pagesize() + 1;
        }, self);
        self.toRecord = ko.computed(function () {
            return Math.min(self.currentPage() * self.pagesize(), self.totalRecords());
        }, self);
        self.totalPages = ko.observable(0);
        self.pageArray = function () {
            var list = [];
            var size = Math.min(self.totalPages(), 9);
            var step;
            if (size < 9 || self.currentPage() === 1)
                step = 0;
            else if (self.currentPage() >= self.totalPages() - 4)
                step = self.totalPages() - 9;
            else
                step = Math.max(self.currentPage() - 5, 0);

            for (var i = 1; i <= size; i++)
                list.push(i + step);
            return list;
        };
        //Colocar a informaçao a funcionar
        self.activate = function (id) {
            console.log('CALL: getDrivers...');
            console.log(self.pagesize)
            var composedUri = self.baseUri() + "?page=" + id + "&pageSize=" + self.pagesize();
            ajaxHelper(composedUri, 'GET').done(function (data) {
                console.log(data);
                self.records(data.List);
                console.log(self.records);
                self.currentPage(data.CurrentPage);
                self.hasNext(data.HasNext);
                self.hasPrevious(data.HasPrevious);
                self.pagesize(data.PageSize)
                self.totalPages(data.PageCount);
                self.totalRecords(data.Total);
            });
        };
        //--- Internal functions
        function ajaxHelper(uri, method, data) {
            self.error(''); // Clear error message
            return $.ajax({
                type: method,
                url: uri,
                dataType: 'json',
                contentType: 'application/json',
                data: data ? JSON.stringify(data) : null,
                error: function (jqXHR, textStatus, errorThrown) {
                    console.log("AJAX Call[" + uri + "] Fail...");
                    self.error(errorThrown);
                }
            });
        }

        function getUrlParameter(sParam) {
            var sPageURL = window.location.search.substring(1),
                sURLVariables = sPageURL.split('&'),
                sParameterName,
                i;
            console.log("sPageURL=", sPageURL);
            for (i = 0; i < sURLVariables.length; i++) {
                sParameterName = sURLVariables[i].split('=');

                if (sParameterName[0] === sParam) {
                    return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
                }
            }

        };

        //--- start ....
        var pg = getUrlParameter('page');
        console.log(pg);
        if (pg == undefined)
            self.activate(1);
        else {
            self.activate(pg);
        }

        self.selectNationality.subscribe(self.AllNationalities);
        self.selectNationality.subscribe(self.AllRaces);
    };

    $(document).ready(function () {
        console.log("ready!");
        ko.applyBindings(new vm());

    });

</code>```

答: You should consider using the 'options' binding: https://knockoutjs.com/documentation/options-binding.html</p>

Body:
So, I'm getting some problems of how to get the value of the selected option in data-bind with foreach, for example, in the second one select that I have in the code html. How can I get the value of the selected option at the moment?

I tried to follow an example that I had, but I'm failing to make it happen in this one.
In resume, what is the command to get the value of the selected option.

 **HTML**
        <select id="corridas" data-bind="value: selectRace, foreach : races," aria-  label="CORRIDAS">
            <option data-bind="text: Name" ></option>
        </select>
        <select id="nacionalidade" data-bind="value: selectNationality, foreach : nationalities" aria-label="NACIONALIDADES">
            <option data-bind="text:Name"></option>
        </select>

JS:

var vm = function () {
        console.log('ViewModel initiated...');
        //---Variáveis locais
        var self = this;
        self.baseUri = ko.observable('http://192.168.160.58/Formula1/api/drivers');
        self.baseUri1 = ko.observable('http://192.168.160.58/Formula1/api/Nationalities');
        self.baseUri2 = ko.observable('http://192.168.160.58/Formula1/api/Races');
        //Variaveis para drivers
        self.error = ko.observable('');
        self.passingMessage = ko.observable('');
        self.records = ko.observableArray([]);
        self.currentPage = ko.observable(1);
        self.pagesize = ko.observable(10);
        self.totalRecords = ko.observable(50);
        self.hasPrevious = ko.observable(false);
        self.hasNext = ko.observable(false);

        //Variaveis para nacionalidades
        self.selectNationality = ko.observable(null);
        self.nationalities = ko.observableArray([]);
        console.log("Here")
        console.log(self.selectNationality)

        // Funçao para obter a List onde irei buscar toda a informaçao das Nationalities
        self.AllNationalities = function () {
            console.log('CALL: Get NATIONALITIES ...');
            var composedUri1 = self.baseUri1()
            ajaxHelper(composedUri1, 'GET').done(function (data) {
                console.log(self.selectNationality)
                self.nationalities(data.List);
            });
        };

        //Variaveis para corridas
        self.selectRace = ko.observable(null);
        self.races = ko.observableArray([]);

        //Funcao para obter a List onde irei buscar toda a informaçao das Races
        self.AllRaces = function () {
            console.log('CALL: GET RACES...');
            var composedUri2 = self.baseUri2()
            ajaxHelper(composedUri2, 'GET').done(function (data) {
                self.races(data.List);
            });
        }

        //Paginação
        self.previousPage = ko.computed(function () {
            return self.currentPage() * 1 - 1;
        }, self);
        self.nextPage = ko.computed(function () {
            return self.currentPage() * 1 + 1;
        }, self);
        self.fromRecord = ko.computed(function () {
            return self.previousPage() * self.pagesize() + 1;
        }, self);
        self.toRecord = ko.computed(function () {
            return Math.min(self.currentPage() * self.pagesize(), self.totalRecords());
        }, self);
        self.totalPages = ko.observable(0);
        self.pageArray = function () {
            var list = [];
            var size = Math.min(self.totalPages(), 9);
            var step;
            if (size < 9 || self.currentPage() === 1)
                step = 0;
            else if (self.currentPage() >= self.totalPages() - 4)
                step = self.totalPages() - 9;
            else
                step = Math.max(self.currentPage() - 5, 0);

            for (var i = 1; i <= size; i++)
                list.push(i + step);
            return list;
        };
        //Colocar a informaçao a funcionar
        self.activate = function (id) {
            console.log('CALL: getDrivers...');
            console.log(self.pagesize)
            var composedUri = self.baseUri() + "?page=" + id + "&pageSize=" + self.pagesize();
            ajaxHelper(composedUri, 'GET').done(function (data) {
                console.log(data);
                self.records(data.List);
                console.log(self.records);
                self.currentPage(data.CurrentPage);
                self.hasNext(data.HasNext);
                self.hasPrevious(data.HasPrevious);
                self.pagesize(data.PageSize)
                self.totalPages(data.PageCount);
                self.totalRecords(data.Total);
            });
        };
        //--- Internal functions
        function ajaxHelper(uri, method, data) {
            self.error(''); // Clear error message
            return $.ajax({
                type: method,
                url: uri,
                dataType: 'json',
                contentType: 'application/json',
                data: data ? JSON.stringify(data) : null,
                error: function (jqXHR, textStatus, errorThrown) {
                    console.log("AJAX Call[" + uri + "] Fail...");
                    self.error(errorThrown);
                }
            });
        }

        function getUrlParameter(sParam) {
            var sPageURL = window.location.search.substring(1),
                sURLVariables = sPageURL.split('&'),
                sParameterName,
                i;
            console.log("sPageURL=", sPageURL);
            for (i = 0; i < sURLVariables.length; i++) {
                sParameterName = sURLVariables[i].split('=');

                if (sParameterName[0] === sParam) {
                    return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
                }
            }

        };

        //--- start ....
        var pg = getUrlParameter('page');
        console.log(pg);
        if (pg == undefined)
            self.activate(1);
        else {
            self.activate(pg);
        }

        self.selectNationality.subscribe(self.AllNationalities);
        self.selectNationality.subscribe(self.AllRaces);
    };

    $(document).ready(function () {
        console.log("ready!");
        ko.applyBindings(new vm());

    });


问:
How to run Scrapy spiders in Celery
There are several posts regarding how to setup Scrapy within a Celery task avoiding to restart the Twister reactor to prevent the twisted.internet.error.ReactorNotRestartable error. I have tried   using CrawlerRunner as recommended on docs and crochet but to make it work the following lines have to be removed from the code:

```<code>d.addBoth(lambda _: reactor.stop())
reactor.run() # Script blocks here until spider finishes.
</code>```

This is the full code:

```<code>from scrapy.crawler import CrawlerRunner

@app.task(bind=True, name="run_spider")
def run_spider(self, my_spider_class, my_spider_settings):
    from crochet import setup
    setup()  # Fixes the issue with Twisted reactor.
    runner = CrawlerRunner(my_spider_settings)
    crawler = runner.create_crawler(my_spider_class)
    runner.crawl(crawler)
    d = runner.join()

    def spider_finished(_):   <-- This function is called when spider finishes.
        logger.info("{} finished:\n{}".format(
            spider_name,
            json.dumps(
                crawler.stats.spider_stats.get(spider_name, {}),
                cls=DjangoJSONEncoder,
                indent=4
            )
        ))

    d.addBoth(spider_finished)
    return f"{spider_name} started" <-- How to block execution until spider finishes?
</code>```

Now works but the Spider seems to be running detached from the task, so I get the return response before the spider is finished. I have used a workaround with the callback spider_finished() but is not ideal because the celery worker keeps running an executing other tasks and eventually kills the process affecting the detached spiders.

Is there a way to block the execution of the task until the Scrapy spider is done?

答:
From doc:

It’s recommended you use CrawlerRunner instead of CrawlerProcess if
your application is already using Twisted and you want to run Scrapy
in the same reactor.

Celery does not use a reactor, so u cant use CrawlerRunner.

Run a Scrapy spider in a Celery Task

Title: How to run Scrapy spiders in Celery

Body:
There are several posts regarding how to setup Scrapy within a Celery task avoiding to restart the Twister reactor to prevent the twisted.internet.error.ReactorNotRestartable error. I have tried   using CrawlerRunner as recommended on docs and crochet but to make it work the following lines have to be removed from the code:

d.addBoth(lambda _: reactor.stop())
reactor.run() # Script blocks here until spider finishes.

This is the full code:

from scrapy.crawler import CrawlerRunner

@app.task(bind=True, name="run_spider")
def run_spider(self, my_spider_class, my_spider_settings):
    from crochet import setup
    setup()  # Fixes the issue with Twisted reactor.
    runner = CrawlerRunner(my_spider_settings)
    crawler = runner.create_crawler(my_spider_class)
    runner.crawl(crawler)
    d = runner.join()

    def spider_finished(_):   <-- This function is called when spider finishes.
        logger.info("{} finished:\n{}".format(
            spider_name,
            json.dumps(
                crawler.stats.spider_stats.get(spider_name, {}),
                cls=DjangoJSONEncoder,
                indent=4
            )
        ))

    d.addBoth(spider_finished)
    return f"{spider_name} started" <-- How to block execution until spider finishes?

Now works but the Spider seems to be running detached from the task, so I get the return response before the spider is finished. I have used a workaround with the callback spider_finished() but is not ideal because the celery worker keeps running an executing other tasks and eventually kills the process affecting the detached spiders.

Is there a way to block the execution of the task until the Scrapy spider is done?


问:
DBD::SQLite Placeholder for integer value in HAVING clause
Since similar statements using DBD::mysql seem to work fine, where is my mistake in using a placeholder for an integer in a HAVING clause, when using DBD::SQLite as DBI driver?

#!/usr/bin/perl

use 5.012;
use warnings;

use DBI;

my $dbh = DBI->connect("dbi:SQLite:dbname=/tmp/test.sqlite","","", {
    RaiseError => 1,
    sqlite_allow_multiple_statements => 1,
});

$dbh->do( <<'EOT' );
CREATE TABLE cd (
    id    INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT
);

CREATE TABLE artist (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    cd   INTEGER,
    FOREIGN KEY (cd) REFERENCES cd (id)
);

INSERT INTO cd (title) VALUES ('foo');
INSERT INTO cd (title) VALUES ('bar');

INSERT INTO artist (name, cd) VALUES ('max fob', 1);
INSERT INTO artist (name, cd) VALUES ('max baz', 1);
EOT

my $sth1 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = 2
EOT

my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = ?
EOT

$sth1->execute('max%');
# says 'hit'
say 'sth1: hit' if $sth1->fetch;

$sth2->execute('max%', 2);
# stays silent
say 'sth2: hit' if $sth2->fetch;
```

Thank you, DDL.

答:
I don't know why the placeholder is treated as a string[1], but you can get the code to work by making SQLite treat the value as an integer. Both of the following solutions are means of achieving this:

my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = ?
EOT

$sth2->bind_param(1, 'max%');
$sth2->bind_param(2, 2, DBI::SQL_INTEGER);
$sth2->execute();
```
<pre class="lang-perl prettyprint-override"><code>my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = CAST( ? AS INTEGER )
EOT

$sth2->execute('max%', 2);
</code>```

The other answer claims that placeholders are always treated as strings. Not only is this not an explanation, it's not even true. This unbacked claim of theirs is obviously false since bind_param can cause placeholders to be treated as something other than a string.

Body:
Since similar statements using DBD::mysql seem to work fine, where is my mistake in using a placeholder for an integer in a HAVING clause, when using DBD::SQLite as DBI driver?

#!/usr/bin/perl

use 5.012;
use warnings;

use DBI;

my $dbh = DBI->connect("dbi:SQLite:dbname=/tmp/test.sqlite","","", {
    RaiseError => 1,
    sqlite_allow_multiple_statements => 1,
});

$dbh->do( <<'EOT' );
CREATE TABLE cd (
    id    INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT
);

CREATE TABLE artist (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT,
    cd   INTEGER,
    FOREIGN KEY (cd) REFERENCES cd (id)
);

INSERT INTO cd (title) VALUES ('foo');
INSERT INTO cd (title) VALUES ('bar');

INSERT INTO artist (name, cd) VALUES ('max fob', 1);
INSERT INTO artist (name, cd) VALUES ('max baz', 1);
EOT

my $sth1 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = 2
EOT

my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = ?
EOT

$sth1->execute('max%');
# says 'hit'
say 'sth1: hit' if $sth1->fetch;

$sth2->execute('max%', 2);
# stays silent
say 'sth2: hit' if $sth2->fetch;

Thank you, DDL.

Body:
I don't know why the placeholder is treated as a string[1], but you can get the code to work by making SQLite treat the value as an integer. Both of the following solutions are means of achieving this:

my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = ?
EOT

$sth2->bind_param(1, 'max%');
$sth2->bind_param(2, 2, DBI::SQL_INTEGER);
$sth2->execute();

my $sth2 = $dbh->prepare(<<'EOT');
   SELECT cd.title
     FROM cd
LEFT JOIN artist ON artist.cd = cd.id
    WHERE artist.name LIKE ?
 GROUP BY cd.title
   HAVING count( artist.cd ) = CAST( ? AS INTEGER )
EOT

$sth2->execute('max%', 2);

The other answer claims that placeholders are always treated as strings. Not only is this not an explanation, it's not even true. This unbacked claim of theirs is obviously false since bind_param can cause placeholders to be treated as something other than a string.