问:
How to manually align, change size, and add scroll pane of JTable?
I am creating a JTable in Netbeans and am having three minor issues with the structure.

I can't seem to align my table in the direction I want (Say North, East, South, or West) and now it's annoyingly hovering over my JButton.

The code I wrote to set the dimensions of the JTable do nothing if I change the variables.

The code I wrote to add a JScrollPane is not showing up when I run it.

I understand if you can't solve all three but I figured I'd put them all in one instead of three different questions so any help with a problem is appreciated!

**Also as a note, ignore everything after the ActionListener. I am eventually going to make the code read a text file and sort that data in an ArrayList. Then somehow into the table instead of how I manually set it up in this example.

Here is my code (problem areas are labeled in comments in bold, capitalized font):

Main:

```<code>package libraryinventory;

import javax.swing.JFrame;
import java.io.*;

public class MainClass {

    static String[] bookArray;

    public static void main(String[] args) {

        GUICommandFunctions guiDemo = new GUICommandFunctions();
        //What to do when window closes
        guiDemo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // size of window in pixels
        guiDemo.setSize(1000, 720);
        //make window visible
        guiDemo.setVisible(true);

    }

}
</code>```

GUI Class:

```<code>package libraryinventory;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.*;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import static javax.swing.Box.createHorizontalBox;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

public class GUICommandFunctions extends JFrame {

    private JButton ButtonOne;
    private JTable jt;

    public GUICommandFunctions() {

        this.setTitle("Library Inventory"); //Name of window

        JPanel panel = new JPanel();
        this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

        ButtonOne = LibraryContentButton();
        panel.add(ButtonOne); //adding panel to JFrame

        String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
        String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
                           {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}
        };

        jt = new JTable(data, columns){ //Makes it so can't edit data inside table once ran
            public boolean isCellEditable(int data, int columns) {
                    return false;
            }
        };

        jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
        jt.setFillsViewportHeight(true); //Set visible
        jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**

        JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
        add(jps);

    }

        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(rootPane, "Eventually will make this button load up the JTable");
                }
            });
            return content;

        }

    static {

        int arrayCount;

        FileReader fr = null;

        try {
            fr = new FileReader("C:\\Users\\Mark Case\\Documents\\NetBeansProjects\\LibraryInventory\\src\\libraryinventory\\library.txt"); //Reads in text file
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        BufferedReader reader = new BufferedReader(fr);
        ArrayList<String> str = new ArrayList<>();
        String line = "";
        arrayCount = 0;
        try {
            while((line=reader.readLine())!=null) {
                str.add(line);
                arrayCount = arrayCount + 1;

            }
        } catch (IOException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
        String selType = "2";

        // Call method to select Books by category type
        String methodResult = SelectType(str, arrayCount, selType);

    }

    private static String SelectType (ArrayList<String> str, int arrayCount, String selType) {
        for (int i = 1; i < arrayCount; i++) {

            String buffer = str.get(i);
            String bookCat = buffer.substring(0,1);

            // Print books by Category - "0" type means print all Books
            if (selType.equals(bookCat)) {
                System.out.println(buffer);
            }
            else if (selType.equals("0")) {
                System.out.println(buffer);
            }
        }
        return "0";
    }

}
</code>```

答:
So, let's take a quick look at the constructor...

```<code>public GUICommandFunctions() {
    //...
    JPanel panel = new JPanel();
    this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

    ButtonOne = LibraryContentButton();
    panel.add(ButtonOne); //adding panel to JFrame
    //...
    jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
    jt.setFillsViewportHeight(true); //Set visible
    jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**

    JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
    add(jps);
}
</code>```

You add panel to the CENTER.  Since you've extended directly from JFrame, the layout is already BorderLayout, so this is fine.

But then you add jps using add(jps);, which will add the component to the layouts default position, which in the case of BorderLayout is CENTER.  This is problematic, as BorderLayout only allows a single component to be managed at each position, which explains why you're setPreferredScrollableViewportSize isn't working, as the BorderLayout is ignoring it, and making the component fill the available space in the CENTER

So, I modified your code.  First, I extended from JPanel instead of JFrame.  It's generally discouraged to extend from JFrame directly, you're not adding any new functionality to the class, locking yourself into a single use case and it generally just makes you live more difficult.

Secondly, I placed the JScrollPane at the SOUTH position of the BorderLayout

```<code>import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new GUICommandFunctionsPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GUICommandFunctionsPane extends JPanel {

        private JButton ButtonOne;
        private JTable jt;

        public GUICommandFunctionsPane() {
            setLayout(new BorderLayout());
            JPanel panel = new JPanel();
            this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

            ButtonOne = LibraryContentButton();
            panel.add(ButtonOne); //adding panel to JFrame

            String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
            String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
            {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}
            };

            jt = new JTable(data, columns) { //Makes it so can't edit data inside table once ran
                public boolean isCellEditable(int data, int columns) {
                    return false;
                }
            };

            jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
            jt.setFillsViewportHeight(true); //Set visible

            JScrollPane jps = new JScrollPane(jt);
            add(jps, BorderLayout.SOUTH);

        }

        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(GUICommandFunctionsPane.this, "Eventually will make this button load up the JTable");
                }
            });
            return content;

        }

//        static {
//
//            int arrayCount;
//
//            FileReader fr = null;
//
//            try {
//                fr = new FileReader("C:\\Users\\Mark Case\\Documents\\NetBeansProjects\\LibraryInventory\\src\\libraryinventory\\library.txt"); //Reads in text file
//            } catch (FileNotFoundException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            BufferedReader reader = new BufferedReader(fr);
//            ArrayList<String> str = new ArrayList<>();
//            String line = "";
//            arrayCount = 0;
//            try {
//                while ((line = reader.readLine()) != null) {
//                    str.add(line);
//                    arrayCount = arrayCount + 1;
//
//                }
//            } catch (IOException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
//            String selType = "2";
//
//            // Call method to select Books by category type
//            String methodResult = SelectType(str, arrayCount, selType);
//
//        }
//
//        private static String SelectType(ArrayList<String> str, int arrayCount, String selType) {
//            for (int i = 1; i < arrayCount; i++) {
//
//                String buffer = str.get(i);
//                String bookCat = buffer.substring(0, 1);
//
//                // Print books by Category - "0" type means print all Books
//                if (selType.equals(bookCat)) {
//                    System.out.println(buffer);
//                } else if (selType.equals("0")) {
//                    System.out.println(buffer);
//                }
//            }
//            return "0";
//        }
    }
}
</code>```

Oh, and I would discourage you from using a static initialiser this way, instead, this either needs to go into the constructor, or, you should use some form of dependency injection to pass the information to the class

Body:
I am creating a JTable in Netbeans and am having three minor issues with the structure.

I can't seem to align my table in the direction I want (Say North, East, South, or West) and now it's annoyingly hovering over my JButton.

The code I wrote to set the dimensions of the JTable do nothing if I change the variables.

The code I wrote to add a JScrollPane is not showing up when I run it.

I understand if you can't solve all three but I figured I'd put them all in one instead of three different questions so any help with a problem is appreciated!

**Also as a note, ignore everything after the ActionListener. I am eventually going to make the code read a text file and sort that data in an ArrayList. Then somehow into the table instead of how I manually set it up in this example.

Here is my code (problem areas are labeled in comments in bold, capitalized font):

Main:

package libraryinventory;

import javax.swing.JFrame;
import java.io.*;

public class MainClass {

    static String[] bookArray;

    public static void main(String[] args) {

        GUICommandFunctions guiDemo = new GUICommandFunctions();
        //What to do when window closes
        guiDemo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // size of window in pixels
        guiDemo.setSize(1000, 720);
        //make window visible
        guiDemo.setVisible(true);

    }

}

GUI Class:

package libraryinventory;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.*;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.Box;
import static javax.swing.Box.createHorizontalBox;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;

public class GUICommandFunctions extends JFrame {

    private JButton ButtonOne;
    private JTable jt;

    public GUICommandFunctions() {

        this.setTitle("Library Inventory"); //Name of window

        JPanel panel = new JPanel();
        this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

        ButtonOne = LibraryContentButton();
        panel.add(ButtonOne); //adding panel to JFrame

        String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
        String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
                           {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}
        };

        jt = new JTable(data, columns){ //Makes it so can't edit data inside table once ran
            public boolean isCellEditable(int data, int columns) {
                    return false;
            }
        };

        jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
        jt.setFillsViewportHeight(true); //Set visible
        jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**

        JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
        add(jps);

    }

        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(rootPane, "Eventually will make this button load up the JTable");
                }
            });
            return content;

        }

    static {

        int arrayCount;

        FileReader fr = null;

        try {
            fr = new FileReader("C:\\Users\\Mark Case\\Documents\\NetBeansProjects\\LibraryInventory\\src\\libraryinventory\\library.txt"); //Reads in text file
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        BufferedReader reader = new BufferedReader(fr);
        ArrayList<String> str = new ArrayList<>();
        String line = "";
        arrayCount = 0;
        try {
            while((line=reader.readLine())!=null) {
                str.add(line);
                arrayCount = arrayCount + 1;

            }
        } catch (IOException ex) {
            Logger.getLogger(GUICommandFunctions.class.getName()).log(Level.SEVERE, null, ex);
        }

        // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
        String selType = "2";

        // Call method to select Books by category type
        String methodResult = SelectType(str, arrayCount, selType);

    }

    private static String SelectType (ArrayList<String> str, int arrayCount, String selType) {
        for (int i = 1; i < arrayCount; i++) {

            String buffer = str.get(i);
            String bookCat = buffer.substring(0,1);

            // Print books by Category - "0" type means print all Books
            if (selType.equals(bookCat)) {
                System.out.println(buffer);
            }
            else if (selType.equals("0")) {
                System.out.println(buffer);
            }
        }
        return "0";
    }

}

Body:
So, let's take a quick look at the constructor...

public GUICommandFunctions() {
    //...
    JPanel panel = new JPanel();
    this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

    ButtonOne = LibraryContentButton();
    panel.add(ButtonOne); //adding panel to JFrame
    //...
    jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
    jt.setFillsViewportHeight(true); //Set visible
    jt.setVerticalAlignment(JTable.BOTTOM_ALIGNMENT); //**HERE IS PROBLEM #1**

    JScrollPane jps = new JScrollPane(jt); //add scroll **HERE IS PROBLEM #3**
    add(jps);
}

You add panel to the CENTER.  Since you've extended directly from JFrame, the layout is already BorderLayout, so this is fine.

But then you add jps using add(jps);, which will add the component to the layouts default position, which in the case of BorderLayout is CENTER.  This is problematic, as BorderLayout only allows a single component to be managed at each position, which explains why you're setPreferredScrollableViewportSize isn't working, as the BorderLayout is ignoring it, and making the component fill the available space in the CENTER

So, I modified your code.  First, I extended from JPanel instead of JFrame.  It's generally discouraged to extend from JFrame directly, you're not adding any new functionality to the class, locking yourself into a single use case and it generally just makes you live more difficult.

Secondly, I placed the JScrollPane at the SOUTH position of the BorderLayout

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new GUICommandFunctionsPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class GUICommandFunctionsPane extends JPanel {

        private JButton ButtonOne;
        private JTable jt;

        public GUICommandFunctionsPane() {
            setLayout(new BorderLayout());
            JPanel panel = new JPanel();
            this.add(panel, BorderLayout.CENTER); //Location of panel for JButton

            ButtonOne = LibraryContentButton();
            panel.add(ButtonOne); //adding panel to JFrame

            String[] columns = {"Title", "Author/Language", "Publisher", "Page Count", "Version Number/Genre/Topic", "Part of a series/Illustrator"}; //columns of the JTable
            String[][] data = {{"The Keto Cookbook", "Chronicle Books", "304", "English", "Keto Cooking", "null"}, //data under the columns
            {"The Hitchhiker's Guide to the Galaxy", "Del Rey", "224", "Douglas Adams", "Fantasy", "Y"}
            };

            jt = new JTable(data, columns) { //Makes it so can't edit data inside table once ran
                public boolean isCellEditable(int data, int columns) {
                    return false;
                }
            };

            jt.setPreferredScrollableViewportSize(new Dimension(450, 63)); //Set size. **HERE IS PROBLEM #2**
            jt.setFillsViewportHeight(true); //Set visible

            JScrollPane jps = new JScrollPane(jt);
            add(jps, BorderLayout.SOUTH);

        }

        private JButton LibraryContentButton() { //
            JButton content = new JButton("Click to view all content");
            content.setFocusable(false);
            content.setBackground(Color.DARK_GRAY);
            content.setForeground(Color.WHITE);
            content.setFont(new Font("Arial", Font.BOLD, 20));
            content.setToolTipText("Shows content of the entire library in a neatly ordered JTable");
            content.setMargin(new Insets(10, 10, 10, 10));
            content.setPreferredSize(new Dimension(300, 75));

            content.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    JOptionPane.showMessageDialog(GUICommandFunctionsPane.this, "Eventually will make this button load up the JTable");
                }
            });
            return content;

        }

//        static {
//
//            int arrayCount;
//
//            FileReader fr = null;
//
//            try {
//                fr = new FileReader("C:\\Users\\Mark Case\\Documents\\NetBeansProjects\\LibraryInventory\\src\\libraryinventory\\library.txt"); //Reads in text file
//            } catch (FileNotFoundException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            BufferedReader reader = new BufferedReader(fr);
//            ArrayList<String> str = new ArrayList<>();
//            String line = "";
//            arrayCount = 0;
//            try {
//                while ((line = reader.readLine()) != null) {
//                    str.add(line);
//                    arrayCount = arrayCount + 1;
//
//                }
//            } catch (IOException ex) {
//                Logger.getLogger(GUICommandFunctionsPane.class.getName()).log(Level.SEVERE, null, ex);
//            }
//
//            // Here we would actually set the type to what the user wants (note: Set it to a "0" if the user wants all Books)
//            String selType = "2";
//
//            // Call method to select Books by category type
//            String methodResult = SelectType(str, arrayCount, selType);
//
//        }
//
//        private static String SelectType(ArrayList<String> str, int arrayCount, String selType) {
//            for (int i = 1; i < arrayCount; i++) {
//
//                String buffer = str.get(i);
//                String bookCat = buffer.substring(0, 1);
//
//                // Print books by Category - "0" type means print all Books
//                if (selType.equals(bookCat)) {
//                    System.out.println(buffer);
//                } else if (selType.equals("0")) {
//                    System.out.println(buffer);
//                }
//            }
//            return "0";
//        }
    }
}

Oh, and I would discourage you from using a static initialiser this way, instead, this either needs to go into the constructor, or, you should use some form of dependency injection to pass the information to the class


来源: stackexchange

问:
Azure DevOps - Pipeline triggering pipeline
Like many before me I'm struggling hard with configuring pipeline triggers in Azure DevOps.

Background:

single project in the Organization

three branches: main, Infrastructure, Application
The branches are kind of independent of each other. They are never merged into main either.

I have a pipeline which deploys two App Services. The YAML file for this pipeline is in the Infrastructure branch. The Default branch for manual and scheduled builds is set to Infrastructure.
Then I have 2 pipelines, each to deploy a different App to the App Service. The YAMLs for those pipelines are in the Application branch. The Default branch for manual and scheduled builds is set to Application.

By themselves, the pipelines work perfectly fine. However what I am trying to achieve is to trigger the App pipelines after the App Service pipeline finishes. And no matter what combination of settings I try, I can't get it to work.

This is currently how it looks like in the n-th version of the YAML:

```<code>name: 'deploy-webapp-002'
pool:
  vmImage: windows-latest

resources:
  pipelines:
  - pipeline: 'Deploy App Services'   # Internal name of the source pipeline, used elsewhere within this YAML
                            # e.g. to reference published artifacts
    source: deploy-appservices # Azure Pipelines name of the source pipeline referenced
    project: HomeLab # Required only if the source pipeline is in another project
    trigger:
      branches:
        include:
        - Infrastructure
        - Application

pr: none
trigger: none
</code>```

Is it even possible to do what I'm trying to do?
If yes, what settings should be specified in the Resources/Pipelines section in the YAML, and how should the Default branch for manual and scheduled builds look like for each of those pipelines?

答:
I can reproduce the same issue when I put the YAML files separately in two branches and set the default branch.

Refer to this doc: Define a pipelines resource

When you define a resource trigger, if its pipeline resource is from the same repository (say self) as the current pipeline, triggering follows the same branch and commit on which the event is raised. But, if the pipeline resource is from a different repository, the current pipeline triggers on the default branch of the self repository.

In your case， you are using the same repo. So triggering follows the same branch and commit on which the event is raised.

To solve this issue, you need to copy the YAML file in Application Branch to  Infrastructure Branch.

On the other hand, you can also try to set Build completion trigger manually on UI.

For example:

ContentLicense: CC BY-SA 4.0

Body:
Like many before me I'm struggling hard with configuring pipeline triggers in Azure DevOps.

Background:

single project in the Organization

three branches: main, Infrastructure, Application
The branches are kind of independent of each other. They are never merged into main either.

I have a pipeline which deploys two App Services. The YAML file for this pipeline is in the Infrastructure branch. The Default branch for manual and scheduled builds is set to Infrastructure.
Then I have 2 pipelines, each to deploy a different App to the App Service. The YAMLs for those pipelines are in the Application branch. The Default branch for manual and scheduled builds is set to Application.

By themselves, the pipelines work perfectly fine. However what I am trying to achieve is to trigger the App pipelines after the App Service pipeline finishes. And no matter what combination of settings I try, I can't get it to work.

This is currently how it looks like in the n-th version of the YAML:

name: 'deploy-webapp-002'
pool:
  vmImage: windows-latest

resources:
  pipelines:
  - pipeline: 'Deploy App Services'   # Internal name of the source pipeline, used elsewhere within this YAML
                            # e.g. to reference published artifacts
    source: deploy-appservices # Azure Pipelines name of the source pipeline referenced
    project: HomeLab # Required only if the source pipeline is in another project
    trigger:
      branches:
        include:
        - Infrastructure
        - Application

pr: none
trigger: none

Is it even possible to do what I'm trying to do?
If yes, what settings should be specified in the Resources/Pipelines section in the YAML, and how should the Default branch for manual and scheduled builds look like for each of those pipelines?


问:
Dynamics CRM: Is there a way to impersonate OrganizationData service?
I have some legacy code which for now I want to reuse in rewritten application. This code was used in silverlight, where user credential where available, but now it is supposed to run on server, so I need to impersonate it. Unfortunately, the code uses CRM OrganizationData service (https://crm/OnBoarding/XRMServices/2011/OrganizationData.svc/) and I cannot find any way to turn impersonation on.

Is there a way to do it? I would like to avoid using NTLM.

答:
After connecting the CrmServiceClient with System Administrator credentials you are able to set the CallerId property to impersonate the user.

CallerId would be the SystemUserId on SystemUser.


问:
Specific structure array string gets skipped when printed
I am creating a program that takes data from a text file and stores it into a structure array. I used strcpy to do that for all string values that I had to store. Every line in this file is a different parameter.

Below is an example of how I accomplished that; I am aware that there are certainly much better ways of going about this task however I am still very much a beginner in C and this is all I could muster.

Input data sample:

```<code>A-0123-21
John
Doe
1 | 4 | 19 | 5 | 62 | 0 | 13 | 5 | 1 | 61 |
----------------------------------------------
</code>```

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
}students;

typedef struct raw
{
    char score[70];
    char divider[70];
}data;

students st[120];
data rw[120];

void init_load()
{
    FILE * fp;
    char line[100];
    if((fp=fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    bool s1=false,s2=false,s3=false,s4=false,s5=false;

    int id=0;
    while (fgets(line, 100, fp) != NULL)
    {

        if (s5 == true)
        {
            s1=false; s2=false; s3=false; s4=false; s5=false;
            strcpy(((st+id)->index), line);
            s1=true;
            id++;

        }else if (s4 == true)
        {
            strcpy(((rw+id)->divider), line);
            s5=true;
        }else if (s3 == true)
        {
            strcpy(((rw+id)->score), line);
            s4=true;
        }else if(s2 == true)
        {
            strcpy(((st+id)->surname), line);
            s3=true;
        }else if(s1 == true)
        {
            strcpy(((st+id)->name), line);
            s2=true;
        }else
        {
            strcpy(((st+id)->index), line);
            s1=true;
        }
    }
    fclose(fp);
```
<p>This code seemingly works fine here. If I add <code>printf("%s", (st+id)->name);</code> to this loop it will print the names with no issues or extra characters.</p>
<p>However, when I call the same <code>printf</code> in a print function it skips the string as if it had an escape sequence. For example:</p>
<pre class="lang-c prettyprint-override"><code>void print_students()
{
    for(int i=0;i<120;i++)
    {
        printf("%s", (st+i)->index);
        printf("%s", (st+i)->name);
        printf("%s", (st+i)->surname);
    }
}
</code>```

The name string gets skipped, but the other ones print out just fine even though I applied the same logic to all of them. Here is what happens after this code is run:

```<code>I-0482-20
Smith
I-0495-20
Simonian
I-0494-20
Sullivan
</code>```

I am sorry for any glaring mistakes but as I've stated earlier I am still learning.

答:
Your primary problem is in the management of the 5 boolean variables.

Data

Here's a data file with 4 entries:

A-0123-21
John
Doe
83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55
----------------------------------------------
A-0124-52
William
Joyce
67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38
----------------------------------------------
A-2124-59
Susan
Winterbourne
30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65
----------------------------------------------
A-2374-63
Sally
Zacharias
42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86
----------------------------------------------
```
<h3>Minimally revised code</h3>
<p>Here's a minimal adaptation of your code — primarily adding the newline handling and debug printing (source <code>io53.c</code>, program <code>io53</code>).  Note that you have 6 blocks of code to handle 5 different types of line; this is another part of your problems, I think.</p>
<pre class="lang-c prettyprint-override"><code>#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
} students;

typedef struct raw
{
    char score[70];
    char divider[70];
} data;

static int count;
static students st[120];
static data rw[120];

static void init_load(void)
{
    FILE *fp;
    char line[100];
    if ((fp = fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    bool s1 = false, s2 = false, s3 = false, s4 = false, s5 = false;

    int id = 0;
    while (fgets(line, 100, fp) != NULL)
    {
        line[strcspn(line, "\n\r")] = '\0';
        printf("Read: [[%s]]\n", line);
        if (s5 == true)
        {
            s1 = false;
            s2 = false;
            s3 = false;
            s4 = false;
            s5 = false;
            strcpy(((st + id)->index), line);
            printf("[%d] index1  [[%s]]\n", id, st[id].index);
            s1 = true;
            id++;
        }
        else if (s4 == true)
        {
            strcpy(((rw + id)->divider), line);
            printf("[%d] divider [[%s]]\n", id, rw[id].divider);
            s5 = true;
        }
        else if (s3 == true)
        {
            strcpy(((rw + id)->score), line);
            printf("[%d] score   [[%s]]\n", id, rw[id].score);
            s4 = true;
        }
        else if (s2 == true)
        {
            strcpy(((st + id)->surname), line);
            printf("[%d] surname [[%s]]\n", id, st[id].surname);
            s3 = true;
        }
        else if (s1 == true)
        {
            strcpy(((st + id)->name), line);
            printf("[%d] name    [[%s]]\n", id, st[id].name);
            s2 = true;
        }
        else
        {
            printf("[%d] index2  [[%s]]\n", id, st[id].index);
            strcpy(((st + id)->index), line);
            s1 = true;
        }
    }
    count = id;
    fclose(fp);
}

static void print_students(void)
{
    for (int i = 0; i < count; i++)
    {
        printf("[%d].index   [[%s]]\n", i, (st + i)->index);
        printf("[%d].name    [[%s]]\n", i, (st + i)->name);
        printf("[%d].surname [[%s]]\n", i, (st + i)->surname);
    }
}

int main(void)
{
    init_load();
    puts("\n");
    print_students();
    return 0;
}
</code>```

Output:

Read: [[A-0123-21]]
[0] index2  [[]]
Read: [[John]]
[0] name    [[John]]
Read: [[Doe]]
[0] surname [[Doe]]
Read: [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
[0] score   [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
Read: [[----------------------------------------------]]
[0] divider [[----------------------------------------------]]
Read: [[A-0124-52]]
[0] index1  [[A-0124-52]]
Read: [[William]]
[1] name    [[William]]
Read: [[Joyce]]
[1] surname [[Joyce]]
Read: [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
[1] score   [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
Read: [[----------------------------------------------]]
[1] divider [[----------------------------------------------]]
Read: [[A-2124-59]]
[1] index1  [[A-2124-59]]
Read: [[Susan]]
[2] name    [[Susan]]
Read: [[Winterbourne]]
[2] surname [[Winterbourne]]
Read: [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
[2] score   [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
Read: [[----------------------------------------------]]
[2] divider [[----------------------------------------------]]
Read: [[A-2374-63]]
[2] index1  [[A-2374-63]]
Read: [[Sally]]
[3] name    [[Sally]]
Read: [[Zacharias]]
[3] surname [[Zacharias]]
Read: [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
[3] score   [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
Read: [[----------------------------------------------]]
[3] divider [[----------------------------------------------]]

[0].index   [[A-0124-52]]
[0].name    [[John]]
[0].surname [[Doe]]
[1].index   [[A-2124-59]]
[1].name    [[William]]
[1].surname [[Joyce]]
[2].index   [[A-2374-63]]
[2].name    [[Susan]]
[2].surname [[Winterbourne]]
```
<p>Note that you didn't go through the <code>index1</code> code block again, so <code>id</code> did not get incremented, so effectively, the last student got left out of the printing, even though the data was read.</p>
<h3>Revised code</h3>
<p>I don't agree with using the five boolean variables; a simple counter would be much simpler to control.  This code (source <code>io97.c</code>, program <code>io97</code>) increments the <code>id</code> after processing a divider line, which is when a student's data is complete.  The <code>lineno</code> counter runs repeatedly from 0 to 4 because of the loop control — a <code>for</code> loop is remarkably flexible.  If the data file contains a partial student record, the partial record is effectively ignored.</p>
<p>Note that this does not check line lengths so buffer overflows are simple to create.  A student named "Henry Percival Alexander Williamsburg-Montgomery" would cause problems.</p>
<pre class="lang-c prettyprint-override"><code>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
} students;

typedef struct raw
{
    char score[70];
    char divider[70];
} data;

static int count;
static students st[120];
static data rw[120];

static void init_load(void)
{
    FILE *fp;
    char line[100];
    if ((fp = fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    int id = 0;
    for (int lineno = 0; fgets(line, 100, fp) != NULL; lineno = (lineno + 1) % 5)
    {
        line[strcspn(line, "\n\r")] = '\0';
        printf("Read: (%d:%d) [[%s]]\n", id, lineno, line);
        if (lineno == 0)
        {
            strcpy(st[id].index, line);
            printf("[%d] index1  [[%s]]\n", id, st[id].index);
        }
        else if (lineno == 1)
        {
            strcpy(st[id].name, line);
            printf("[%d] name    [[%s]]\n", id, st[id].name);
        }
        else if (lineno == 2)
        {
            strcpy(st[id].surname, line);
            printf("[%d] surname [[%s]]\n", id, st[id].surname);
        }
        else if (lineno == 3)
        {
            strcpy(rw[id].score, line);
            printf("[%d] score   [[%s]]\n", id, rw[id].score);
        }
        else if (lineno == 4)
        {
            strcpy(rw[id].divider, line);
            printf("[%d] divider [[%s]]\n", id, rw[id].divider);
            id++;
        }
        else
        {
            abort();
        }
    }
    count = id;
    fclose(fp);
}

static void print_students(void)
{
    for (int i = 0; i < count; i++)
    {
        printf("[%d].index   [[%s]]\n", i, st[i].index);
        printf("[%d].name    [[%s]]\n", i, st[i].name);
        printf("[%d].surname [[%s]]\n", i, st[i].surname);
    }
}

int main(void)
{
    init_load();
    puts("\n");
    print_students();
    return 0;
}
</code>```

When run on the same data, it produces:

Read: (0:0) [[A-0123-21]]
[0] index1  [[A-0123-21]]
Read: (0:1) [[John]]
[0] name    [[John]]
Read: (0:2) [[Doe]]
[0] surname [[Doe]]
Read: (0:3) [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
[0] score   [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
Read: (0:4) [[----------------------------------------------]]
[0] divider [[----------------------------------------------]]
Read: (1:0) [[A-0124-52]]
[1] index1  [[A-0124-52]]
Read: (1:1) [[William]]
[1] name    [[William]]
Read: (1:2) [[Joyce]]
[1] surname [[Joyce]]
Read: (1:3) [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
[1] score   [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
Read: (1:4) [[----------------------------------------------]]
[1] divider [[----------------------------------------------]]
Read: (2:0) [[A-2124-59]]
[2] index1  [[A-2124-59]]
Read: (2:1) [[Susan]]
[2] name    [[Susan]]
Read: (2:2) [[Winterbourne]]
[2] surname [[Winterbourne]]
Read: (2:3) [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
[2] score   [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
Read: (2:4) [[----------------------------------------------]]
[2] divider [[----------------------------------------------]]
Read: (3:0) [[A-2374-63]]
[3] index1  [[A-2374-63]]
Read: (3:1) [[Sally]]
[3] name    [[Sally]]
Read: (3:2) [[Zacharias]]
[3] surname [[Zacharias]]
Read: (3:3) [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
[3] score   [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
Read: (3:4) [[----------------------------------------------]]
[3] divider [[----------------------------------------------]]

[0].index   [[A-0123-21]]
[0].name    [[John]]
[0].surname [[Doe]]
[1].index   [[A-0124-52]]
[1].name    [[William]]
[1].surname [[Joyce]]
[2].index   [[A-2124-59]]
[2].name    [[Susan]]
[2].surname [[Winterbourne]]
[3].index   [[A-2374-63]]
[3].name    [[Sally]]
[3].surname [[Zacharias]]
```

Body:
I am creating a program that takes data from a text file and stores it into a structure array. I used strcpy to do that for all string values that I had to store. Every line in this file is a different parameter.

Below is an example of how I accomplished that; I am aware that there are certainly much better ways of going about this task however I am still very much a beginner in C and this is all I could muster.

Input data sample:

A-0123-21
John
Doe
1 | 4 | 19 | 5 | 62 | 0 | 13 | 5 | 1 | 61 |
----------------------------------------------

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
}students;

typedef struct raw
{
    char score[70];
    char divider[70];
}data;

students st[120];
data rw[120];

void init_load()
{
    FILE * fp;
    char line[100];
    if((fp=fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    bool s1=false,s2=false,s3=false,s4=false,s5=false;

    int id=0;
    while (fgets(line, 100, fp) != NULL)
    {

        if (s5 == true)
        {
            s1=false; s2=false; s3=false; s4=false; s5=false;
            strcpy(((st+id)->index), line);
            s1=true;
            id++;

        }else if (s4 == true)
        {
            strcpy(((rw+id)->divider), line);
            s5=true;
        }else if (s3 == true)
        {
            strcpy(((rw+id)->score), line);
            s4=true;
        }else if(s2 == true)
        {
            strcpy(((st+id)->surname), line);
            s3=true;
        }else if(s1 == true)
        {
            strcpy(((st+id)->name), line);
            s2=true;
        }else
        {
            strcpy(((st+id)->index), line);
            s1=true;
        }
    }
    fclose(fp);

This code seemingly works fine here. If I add printf("%s", (st+id)->name); to this loop it will print the names with no issues or extra characters.

However, when I call the same printf in a print function it skips the string as if it had an escape sequence. For example:

void print_students()
{
    for(int i=0;i<120;i++)
    {
        printf("%s", (st+i)->index);
        printf("%s", (st+i)->name);
        printf("%s", (st+i)->surname);
    }
}

The name string gets skipped, but the other ones print out just fine even though I applied the same logic to all of them. Here is what happens after this code is run:

I-0482-20
Smith
I-0495-20
Simonian
I-0494-20
Sullivan

I am sorry for any glaring mistakes but as I've stated earlier I am still learning.

Body:
Your primary problem is in the management of the 5 boolean variables.

Data

Here's a data file with 4 entries:

A-0123-21
John
Doe
83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55
----------------------------------------------
A-0124-52
William
Joyce
67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38
----------------------------------------------
A-2124-59
Susan
Winterbourne
30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65
----------------------------------------------
A-2374-63
Sally
Zacharias
42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86
----------------------------------------------

Minimally revised code

Here's a minimal adaptation of your code — primarily adding the newline handling and debug printing (source io53.c, program io53).  Note that you have 6 blocks of code to handle 5 different types of line; this is another part of your problems, I think.

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
} students;

typedef struct raw
{
    char score[70];
    char divider[70];
} data;

static int count;
static students st[120];
static data rw[120];

static void init_load(void)
{
    FILE *fp;
    char line[100];
    if ((fp = fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    bool s1 = false, s2 = false, s3 = false, s4 = false, s5 = false;

    int id = 0;
    while (fgets(line, 100, fp) != NULL)
    {
        line[strcspn(line, "\n\r")] = '\0';
        printf("Read: [[%s]]\n", line);
        if (s5 == true)
        {
            s1 = false;
            s2 = false;
            s3 = false;
            s4 = false;
            s5 = false;
            strcpy(((st + id)->index), line);
            printf("[%d] index1  [[%s]]\n", id, st[id].index);
            s1 = true;
            id++;
        }
        else if (s4 == true)
        {
            strcpy(((rw + id)->divider), line);
            printf("[%d] divider [[%s]]\n", id, rw[id].divider);
            s5 = true;
        }
        else if (s3 == true)
        {
            strcpy(((rw + id)->score), line);
            printf("[%d] score   [[%s]]\n", id, rw[id].score);
            s4 = true;
        }
        else if (s2 == true)
        {
            strcpy(((st + id)->surname), line);
            printf("[%d] surname [[%s]]\n", id, st[id].surname);
            s3 = true;
        }
        else if (s1 == true)
        {
            strcpy(((st + id)->name), line);
            printf("[%d] name    [[%s]]\n", id, st[id].name);
            s2 = true;
        }
        else
        {
            printf("[%d] index2  [[%s]]\n", id, st[id].index);
            strcpy(((st + id)->index), line);
            s1 = true;
        }
    }
    count = id;
    fclose(fp);
}

static void print_students(void)
{
    for (int i = 0; i < count; i++)
    {
        printf("[%d].index   [[%s]]\n", i, (st + i)->index);
        printf("[%d].name    [[%s]]\n", i, (st + i)->name);
        printf("[%d].surname [[%s]]\n", i, (st + i)->surname);
    }
}

int main(void)
{
    init_load();
    puts("\n");
    print_students();
    return 0;
}

Output:

Read: [[A-0123-21]]
[0] index2  [[]]
Read: [[John]]
[0] name    [[John]]
Read: [[Doe]]
[0] surname [[Doe]]
Read: [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
[0] score   [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
Read: [[----------------------------------------------]]
[0] divider [[----------------------------------------------]]
Read: [[A-0124-52]]
[0] index1  [[A-0124-52]]
Read: [[William]]
[1] name    [[William]]
Read: [[Joyce]]
[1] surname [[Joyce]]
Read: [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
[1] score   [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
Read: [[----------------------------------------------]]
[1] divider [[----------------------------------------------]]
Read: [[A-2124-59]]
[1] index1  [[A-2124-59]]
Read: [[Susan]]
[2] name    [[Susan]]
Read: [[Winterbourne]]
[2] surname [[Winterbourne]]
Read: [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
[2] score   [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
Read: [[----------------------------------------------]]
[2] divider [[----------------------------------------------]]
Read: [[A-2374-63]]
[2] index1  [[A-2374-63]]
Read: [[Sally]]
[3] name    [[Sally]]
Read: [[Zacharias]]
[3] surname [[Zacharias]]
Read: [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
[3] score   [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
Read: [[----------------------------------------------]]
[3] divider [[----------------------------------------------]]

[0].index   [[A-0124-52]]
[0].name    [[John]]
[0].surname [[Doe]]
[1].index   [[A-2124-59]]
[1].name    [[William]]
[1].surname [[Joyce]]
[2].index   [[A-2374-63]]
[2].name    [[Susan]]
[2].surname [[Winterbourne]]

Note that you didn't go through the index1 code block again, so id did not get incremented, so effectively, the last student got left out of the printing, even though the data was read.

Revised code

I don't agree with using the five boolean variables; a simple counter would be much simpler to control.  This code (source io97.c, program io97) increments the id after processing a divider line, which is when a student's data is complete.  The lineno counter runs repeatedly from 0 to 4 because of the loop control — a for loop is remarkably flexible.  If the data file contains a partial student record, the partial record is effectively ignored.

Note that this does not check line lengths so buffer overflows are simple to create.  A student named "Henry Percival Alexander Williamsburg-Montgomery" would cause problems.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct student
{
    char index[10];
    char name[23];
    char surname[23];
    int scores[11];
} students;

typedef struct raw
{
    char score[70];
    char divider[70];
} data;

static int count;
static students st[120];
static data rw[120];

static void init_load(void)
{
    FILE *fp;
    char line[100];
    if ((fp = fopen("students.txt", "r")) == NULL)
    {
        printf("File not found \n");
        exit(1);
    }

    int id = 0;
    for (int lineno = 0; fgets(line, 100, fp) != NULL; lineno = (lineno + 1) % 5)
    {
        line[strcspn(line, "\n\r")] = '\0';
        printf("Read: (%d:%d) [[%s]]\n", id, lineno, line);
        if (lineno == 0)
        {
            strcpy(st[id].index, line);
            printf("[%d] index1  [[%s]]\n", id, st[id].index);
        }
        else if (lineno == 1)
        {
            strcpy(st[id].name, line);
            printf("[%d] name    [[%s]]\n", id, st[id].name);
        }
        else if (lineno == 2)
        {
            strcpy(st[id].surname, line);
            printf("[%d] surname [[%s]]\n", id, st[id].surname);
        }
        else if (lineno == 3)
        {
            strcpy(rw[id].score, line);
            printf("[%d] score   [[%s]]\n", id, rw[id].score);
        }
        else if (lineno == 4)
        {
            strcpy(rw[id].divider, line);
            printf("[%d] divider [[%s]]\n", id, rw[id].divider);
            id++;
        }
        else
        {
            abort();
        }
    }
    count = id;
    fclose(fp);
}

static void print_students(void)
{
    for (int i = 0; i < count; i++)
    {
        printf("[%d].index   [[%s]]\n", i, st[i].index);
        printf("[%d].name    [[%s]]\n", i, st[i].name);
        printf("[%d].surname [[%s]]\n", i, st[i].surname);
    }
}

int main(void)
{
    init_load();
    puts("\n");
    print_students();
    return 0;
}

When run on the same data, it produces:

Read: (0:0) [[A-0123-21]]
[0] index1  [[A-0123-21]]
Read: (0:1) [[John]]
[0] name    [[John]]
Read: (0:2) [[Doe]]
[0] surname [[Doe]]
Read: (0:3) [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
[0] score   [[83 | 49 | 78 | 79 | 88 | 34 | 45 | 77 | 40 | 61 | 55]]
Read: (0:4) [[----------------------------------------------]]
[0] divider [[----------------------------------------------]]
Read: (1:0) [[A-0124-52]]
[1] index1  [[A-0124-52]]
Read: (1:1) [[William]]
[1] name    [[William]]
Read: (1:2) [[Joyce]]
[1] surname [[Joyce]]
Read: (1:3) [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
[1] score   [[67 | 47 | 58 | 91 | 88 | 67 | 73 | 30 | 65 | 21 | 38]]
Read: (1:4) [[----------------------------------------------]]
[1] divider [[----------------------------------------------]]
Read: (2:0) [[A-2124-59]]
[2] index1  [[A-2124-59]]
Read: (2:1) [[Susan]]
[2] name    [[Susan]]
Read: (2:2) [[Winterbourne]]
[2] surname [[Winterbourne]]
Read: (2:3) [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
[2] score   [[30 | 80 | 31 | 50 | 29 | 28 | 94 | 36 | 58 | 82 | 65]]
Read: (2:4) [[----------------------------------------------]]
[2] divider [[----------------------------------------------]]
Read: (3:0) [[A-2374-63]]
[3] index1  [[A-2374-63]]
Read: (3:1) [[Sally]]
[3] name    [[Sally]]
Read: (3:2) [[Zacharias]]
[3] surname [[Zacharias]]
Read: (3:3) [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
[3] score   [[42 | 67 | 59 | 57 | 92 | 41 | 77 | 59 | 77 | 50 | 86]]
Read: (3:4) [[----------------------------------------------]]
[3] divider [[----------------------------------------------]]

[0].index   [[A-0123-21]]
[0].name    [[John]]
[0].surname [[Doe]]
[1].index   [[A-0124-52]]
[1].name    [[William]]
[1].surname [[Joyce]]
[2].index   [[A-2124-59]]
[2].name    [[Susan]]
[2].surname [[Winterbourne]]
[3].index   [[A-2374-63]]
[3].name    [[Sally]]
[3].surname [[Zacharias]]


问:
Set legend width to be 100% plot width
How do I set the legend height or width to be 100% of the plot height/width regardless of the actual dimensions?

library(ggplot2)
ggplot(iris, aes(Petal.Width, Sepal.Width, color=Petal.Length))+
  geom_point()+
  theme(
    legend.title=element_blank(),
    legend.position="bottom",
    legend.key.width=unit(0.1,"npc"))
```
<p><img src="https://i.imgur.com/etPvIQL.png" alt="" /></p>
<p><sup>Created on 2022-02-11 by the reprex package (v2.0.1)</sup></p>

Session info

<pre class="lang-r prettyprint-override"><code>sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.1.0 (2021-05-18)
#>  os       Ubuntu 20.04.3 LTS
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  ggplot2     * 3.3.5   2021-06-25 [1] CRAN (R 4.1.0)
#>
#> ──────────────────────────────────────────────────────────────────────────────
</code>```

答:
Here I'll use a very manual way to set the legend width, which is guides(colour = guide_colorbar(barwidth = 25)). Just try out the barwidth parameter, you'll get one that fits the plot.

I'd also love to know a way to easily get the width of the plot, so that we don't need to manually set the barwidth.

UPDATE: As you can see in the comment under this answer, both @teunbrand and I agree that we can use a barwidth value close to the value of fig.width in Rmarkdown or width in ggsave if you are using these utilities to display your graph

```<code>ggplot(iris, aes(Petal.Width, Sepal.Width, color=Petal.Length))+
  geom_point()+
  guides(colour = guide_colorbar(barwidth = 25)) +
  theme(
    legend.title=element_blank(),
    legend.position="bottom")
</code>```

Title: Set legend width to be 100% plot width

Body:
How do I set the legend height or width to be 100% of the plot height/width regardless of the actual dimensions?

library(ggplot2)
ggplot(iris, aes(Petal.Width, Sepal.Width, color=Petal.Length))+
  geom_point()+
  theme(
    legend.title=element_blank(),
    legend.position="bottom",
    legend.key.width=unit(0.1,"npc"))

Created on 2022-02-11 by the reprex package (v2.0.1)

Session info

sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.1.0 (2021-05-18)
#>  os       Ubuntu 20.04.3 LTS
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  ggplot2     * 3.3.5   2021-06-25 [1] CRAN (R 4.1.0)
#>
#> ──────────────────────────────────────────────────────────────────────────────

Body:
Here I'll use a very manual way to set the legend width, which is guides(colour = guide_colorbar(barwidth = 25)). Just try out the barwidth parameter, you'll get one that fits the plot.

I'd also love to know a way to easily get the width of the plot, so that we don't need to manually set the barwidth.

UPDATE: As you can see in the comment under this answer, both @teunbrand and I agree that we can use a barwidth value close to the value of fig.width in Rmarkdown or width in ggsave if you are using these utilities to display your graph

ggplot(iris, aes(Petal.Width, Sepal.Width, color=Petal.Length))+
  geom_point()+
  guides(colour = guide_colorbar(barwidth = 25)) +
  theme(
    legend.title=element_blank(),
    legend.position="bottom")


问:
AutoFixture, xUnit: Setup TypeRelays and inject service in constructor
I am trying to write some tests, I use xUnit.net, Moq, AutoFixture. I need to inject service to my test method:

```<code>[Theory, AutoData]
public void TestSmthCool(IService service)
{
}
</code>```

The IService has 3 dependencies which I want to mock. But, If I run the test I get error:

```<code>AutoFixture was unable to create an instance from Services.Interfaces.IService because it's an interface.
</code>```

So, I fixed it in the following way:

```<code>[Theory, AutoData]
public void TestSmthCool()
{
   var fixture = new Fixture();
   fixture.Customize(new AutoMoqCustomization());
   fixture.Customizations.Add(
      new TypeRelay(
         typeof(IService),
         typeof(MyService)
      )
   );

   var s= fixture.Create<IService>();
}
</code>```

But, how to setup TypeRelay for all tests and inject service via method constructor?

答:
I was just able to do this by wrapping the interface/concrete class implementation in a parameter attribute that adds a customization which in turn creates a TypeRelay

see example below (its in .net 6 by the way)

```<code>public interface IService
{
    string Echo(string val);
}

public class MyService : IService
{
    public string Echo(string val)
    {
        return val + "Example";
    }
}

public interface IService2
{
    string Echo(string val);
}

public class MyService2 : IService2
{
    public string Echo(string val)
    {
        return val + "Example2";
    }
}

public sealed class InterfaceMapCustomization : ICustomization
{
    private readonly Type _interfaceType;
    private readonly Type _concreteType;
    public InterfaceMapCustomization(Type interfaceType, Type concreteType)
    {
        if (!interfaceType.IsAssignableFrom(concreteType))
        {
            throw new ArgumentException($"Type '{concreteType.Name}' does not implement interface '{interfaceType.Name}'");
        }

        _interfaceType = interfaceType;
        _concreteType = concreteType;
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new TypeRelay(_interfaceType, _concreteType));
    }
}

/// <summary>
/// Adds a TypeRelay to the Fixture customizations for the specified interface/class pair
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class InterfaceMapAttribute : CustomizeAttribute
{
    private readonly Type _interfaceType;
    private readonly Type _concreteType;

    /// <summary>
    /// Adds a TypeRelay to the Fixture customizations for the specified interface/class pair
    /// </summary>
    /// <param name="interfaceType">The interface to which we want to map our type to</param>
    /// <param name="concreteType">The class implementing the interface we want to create</param>
    /// <exception cref="InvalidOperationException"></exception>
    public InterfaceMapAttribute(Type interfaceType, Type concreteType)
    {
        if (!interfaceType.IsAssignableFrom(concreteType))
        {
            throw new InvalidOperationException($"Type '{concreteType.Name}' does not implement interface '{interfaceType.Name}'");
        }

        _interfaceType = interfaceType;
        _concreteType = concreteType;
    }

    public override ICustomization GetCustomization(ParameterInfo parameter)
    {
        if (parameter == null)
        {
            throw new InvalidOperationException("Parameter info is null");
        }

        if (parameter.ParameterType != _interfaceType)
        {
            throw new InvalidOperationException($"Parameter '{parameter.Name}' does not implement interface '{_interfaceType.Name}'");
        }

        return new CompositeCustomization(new List<ICustomization>
        {
            new InterfaceMapCustomization(_interfaceType, _concreteType)
        });
    }
}

public class UnitTest1
{

    [Theory]
    [AutoData]
    public void TestSomething(
        string expected,
        [InterfaceMap(typeof(IService), typeof(MyService))] IService sut,
        [InterfaceMap(typeof(IService2), typeof(MyService2))] IService2 sut2
        )
    {
        var result = sut.Echo(expected);

        Assert.Equal(expected + "Example", result);

        var result2 = sut2.Echo(expected);

        Assert.Equal(expected + "Example2", result2);
    }
}
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I am trying to write some tests, I use xUnit.net, Moq, AutoFixture. I need to inject service to my test method:

[Theory, AutoData]
public void TestSmthCool(IService service)
{
}

The IService has 3 dependencies which I want to mock. But, If I run the test I get error:

AutoFixture was unable to create an instance from Services.Interfaces.IService because it's an interface.

So, I fixed it in the following way:

[Theory, AutoData]
public void TestSmthCool()
{
   var fixture = new Fixture();
   fixture.Customize(new AutoMoqCustomization());
   fixture.Customizations.Add(
      new TypeRelay(
         typeof(IService),
         typeof(MyService)
      )
   );

   var s= fixture.Create<IService>();
}

But, how to setup TypeRelay for all tests and inject service via method constructor?

Body:
I was just able to do this by wrapping the interface/concrete class implementation in a parameter attribute that adds a customization which in turn creates a TypeRelay

see example below (its in .net 6 by the way)

public interface IService
{
    string Echo(string val);
}

public class MyService : IService
{
    public string Echo(string val)
    {
        return val + "Example";
    }
}

public interface IService2
{
    string Echo(string val);
}

public class MyService2 : IService2
{
    public string Echo(string val)
    {
        return val + "Example2";
    }
}

public sealed class InterfaceMapCustomization : ICustomization
{
    private readonly Type _interfaceType;
    private readonly Type _concreteType;
    public InterfaceMapCustomization(Type interfaceType, Type concreteType)
    {
        if (!interfaceType.IsAssignableFrom(concreteType))
        {
            throw new ArgumentException($"Type '{concreteType.Name}' does not implement interface '{interfaceType.Name}'");
        }

        _interfaceType = interfaceType;
        _concreteType = concreteType;
    }

    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(new TypeRelay(_interfaceType, _concreteType));
    }
}

/// <summary>
/// Adds a TypeRelay to the Fixture customizations for the specified interface/class pair
/// </summary>
[AttributeUsage(AttributeTargets.Parameter)]
public sealed class InterfaceMapAttribute : CustomizeAttribute
{
    private readonly Type _interfaceType;
    private readonly Type _concreteType;

    /// <summary>
    /// Adds a TypeRelay to the Fixture customizations for the specified interface/class pair
    /// </summary>
    /// <param name="interfaceType">The interface to which we want to map our type to</param>
    /// <param name="concreteType">The class implementing the interface we want to create</param>
    /// <exception cref="InvalidOperationException"></exception>
    public InterfaceMapAttribute(Type interfaceType, Type concreteType)
    {
        if (!interfaceType.IsAssignableFrom(concreteType))
        {
            throw new InvalidOperationException($"Type '{concreteType.Name}' does not implement interface '{interfaceType.Name}'");
        }

        _interfaceType = interfaceType;
        _concreteType = concreteType;
    }

    public override ICustomization GetCustomization(ParameterInfo parameter)
    {
        if (parameter == null)
        {
            throw new InvalidOperationException("Parameter info is null");
        }

        if (parameter.ParameterType != _interfaceType)
        {
            throw new InvalidOperationException($"Parameter '{parameter.Name}' does not implement interface '{_interfaceType.Name}'");
        }

        return new CompositeCustomization(new List<ICustomization>
        {
            new InterfaceMapCustomization(_interfaceType, _concreteType)
        });
    }
}

public class UnitTest1
{

    [Theory]
    [AutoData]
    public void TestSomething(
        string expected,
        [InterfaceMap(typeof(IService), typeof(MyService))] IService sut,
        [InterfaceMap(typeof(IService2), typeof(MyService2))] IService2 sut2
        )
    {
        var result = sut.Echo(expected);

        Assert.Equal(expected + "Example", result);

        var result2 = sut2.Echo(expected);

        Assert.Equal(expected + "Example2", result2);
    }
}


问:
Next.js Image- how to maintain aspect ratio and add letterboxes when needed
I have an area of my Next.js app which is the selected photo of a photo gallery so it has to stay fixed in size as people flip through the selected image or a photo is loading. I have a responsive layout but if really pressed, I'd say that this pixel area is 566px*425px.

I'm confused about how to actually do this. Here's the closest I've been able to get it, but the problem is that I get overflow of the image when the aspect ratio exceeds 566x425 and for images that have an aspect ratio below 566x425 it will stretch it in the Y direct. What I really want is to have a fixed box and then if the aspect ratios differ from the max size, you'll see letterboxes either along the sides or on the top and bottom.

```<code>           <div
            style={{
              position: 'relative',
              width: '566px',
              height: '425px',
            }}
          >
            <Image
              src={currCommit.image.url}
              alt="Current Image"
              layout={'fill'}
              objectFit="cover"
            />
          </div>
</code>```

答:
there's better solution i think, NextImage have callback property onLoadingComplete:

A callback function that is invoked once the image is completely loaded and the placeholder has been removed.

The onLoadingComplete function accepts one parameter, an object with the following properties: naturalWidth, naturalHeight

you can use the natural properties to set image ratio without loosing NextImage's layout functionality like this:

const NaturalImage = (props: ImageProps) => {
  const [ratio, setRatio] = useState(16/9) // default to 16:9

  return (
    <NextImage
      {...props}
      // set the dimension (affected by layout)
      width={200}
      height={200 / ratio}
      layout="fixed" // you can use "responsive", "fill" or the default "intrinsic"
      onLoadingComplete={({ naturalWidth, naturalHeight }) =>
        setRatio(naturalWidth / naturalHeight)
      }
    />
  )
}
```

the only downside is the aspect ratio applied only after image loaded, so the placeholder using the default ratio (in this case 16:9 - common), and this can cause CLS

Body:
I have an area of my Next.js app which is the selected photo of a photo gallery so it has to stay fixed in size as people flip through the selected image or a photo is loading. I have a responsive layout but if really pressed, I'd say that this pixel area is 566px*425px.

I'm confused about how to actually do this. Here's the closest I've been able to get it, but the problem is that I get overflow of the image when the aspect ratio exceeds 566x425 and for images that have an aspect ratio below 566x425 it will stretch it in the Y direct. What I really want is to have a fixed box and then if the aspect ratios differ from the max size, you'll see letterboxes either along the sides or on the top and bottom.

            <Image
              src={currCommit.image.url}
              alt="Current Image"
              layout={'fill'}
              objectFit="cover"
            />

Body:
there's better solution i think, NextImage have callback property onLoadingComplete:

A callback function that is invoked once the image is completely loaded and the placeholder has been removed.

The onLoadingComplete function accepts one parameter, an object with the following properties: naturalWidth, naturalHeight

you can use the natural properties to set image ratio without loosing NextImage's layout functionality like this:

const NaturalImage = (props: ImageProps) => {
  const [ratio, setRatio] = useState(16/9) // default to 16:9

  return (
    <NextImage
      {...props}
      // set the dimension (affected by layout)
      width={200}
      height={200 / ratio}
      layout="fixed" // you can use "responsive", "fill" or the default "intrinsic"
      onLoadingComplete={({ naturalWidth, naturalHeight }) =>
        setRatio(naturalWidth / naturalHeight)
      }
    />
  )
}

the only downside is the aspect ratio applied only after image loaded, so the placeholder using the default ratio (in this case 16:9 - common), and this can cause CLS


问:
Validate Date entered into cell
I have a workbook with a field for a user to enter a date.  In testing, I entered 11/31/21 which is not a valid date.  I thought I would test for valid date entry and can't seem to make it work.  I am trying to use IsDate to check and must being doing something wrong.  I tried setting my cell value as both date and string with no luck.</p>
```<code>Public Sub Worksheet_Change(ByVal Target As Range)
    Dim PCell As Range
    Dim Edate As Date

    Set PCell = Range("S2")
        Edate = Range("S2")

If Not Application.Intersect(PCell, Range(Target.Address)) _
           Is Nothing Then
    If IsDate(Edate) = 1 Then
    ActiveWorkbook.Connections("Query - SelectedDataByDate").Refresh
Else
MsgBox ("You have entered an invalide date.")
End If

End If

End Sub
</code>```

答:
Thanks for your help. @DS_London, it was the case that VBA did not use 1 but rather True and False.

This code ran as expected.

```<code>Public Sub Worksheet_Change(ByVal Target As Range)
    Dim PCell As Range
    Dim Edate As Variant

    Set PCell = Range("S2")
        Edate = Range("S2")

If Not Application.Intersect(PCell, Range(Target.Address)) _
           Is Nothing Then
    If IsDate(Edate) = True Then
    ActiveWorkbook.Connections("Query - SelectedDataByDate").Refresh
Else
MsgBox ("You have entered an invalide date.")
End If

End If

End Sub
</code>```

Title: Validate Date entered into cell

Body:
I have a workbook with a field for a user to enter a date.  In testing, I entered 11/31/21 which is not a valid date.  I thought I would test for valid date entry and can't seem to make it work.  I am trying to use IsDate to check and must being doing something wrong.  I tried setting my cell value as both date and string with no luck.

Public Sub Worksheet_Change(ByVal Target As Range)
    Dim PCell As Range
    Dim Edate As Date

    Set PCell = Range("S2")
        Edate = Range("S2")

If Not Application.Intersect(PCell, Range(Target.Address)) _
           Is Nothing Then
    If IsDate(Edate) = 1 Then
    ActiveWorkbook.Connections("Query - SelectedDataByDate").Refresh
Else
MsgBox ("You have entered an invalide date.")
End If

End If

End Sub

Body:
Thanks for your help. @DS_London, it was the case that VBA did not use 1 but rather True and False.

This code ran as expected.

Public Sub Worksheet_Change(ByVal Target As Range)
    Dim PCell As Range
    Dim Edate As Variant

    Set PCell = Range("S2")
        Edate = Range("S2")

If Not Application.Intersect(PCell, Range(Target.Address)) _
           Is Nothing Then
    If IsDate(Edate) = True Then
    ActiveWorkbook.Connections("Query - SelectedDataByDate").Refresh
Else
MsgBox ("You have entered an invalide date.")
End If

End If

End Sub


问:
Unknown authentication response: 10 Postresql golang
I get an error while connect to postresql with golang

ERROR -----------  pq: unknown authentication response: 10

CODE:

```<code>cfg := config{
    Host:     "localhost",
    Port:     5432,
    Username: "postgres",
    Password: "ellez2004",
    DBname:   "app",
}
pconfig := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",cfg.Host,cfg.Port,cfg.Password,cfg.Password,cfg.DBname)
db,err := sql.Open("postgres",pconfig)
if err != nil {
    log.Fatal(err.Error())
}
defer db.Close();

insert := `insert into "User" ("firstname","lastname") values('Allaz','Bairamov')`
_ ,err = db.Exec(insert);
if err != nil {
    fmt.Println("error ---", err.Error());
}
fmt.Println("success");
http.ListenAndServe(":8000", nil)
</code>```

Please help:)

答:
Seems like there is typo. Should be .Username not .Password

pconfig := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",cfg.Host,cfg.Port,cfg.Password,cfg.Password,cfg.DBname)
```
<p>Else, try make sure all the parameters tally with Postgres Connection</p>
<pre class="lang-golang prettyprint-override"><code>    Host:     "localhost", // where you host your Postgres server
    Port:     5432, // default port for Postgres
    Username: "postgres", // this is user credential to access of the database
    Password: "ellez2004", // corresponding password
    DBname:   "app", // the database schema name
</code>```

Body:
I get an error while connect to postresql with golang

ERROR -----------  pq: unknown authentication response: 10

CODE:

cfg := config{
    Host:     "localhost",
    Port:     5432,
    Username: "postgres",
    Password: "ellez2004",
    DBname:   "app",
}
pconfig := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",cfg.Host,cfg.Port,cfg.Password,cfg.Password,cfg.DBname)
db,err := sql.Open("postgres",pconfig)
if err != nil {
    log.Fatal(err.Error())
}
defer db.Close();

insert := `insert into "User" ("firstname","lastname") values('Allaz','Bairamov')`
_ ,err = db.Exec(insert);
if err != nil {
    fmt.Println("error ---", err.Error());
}
fmt.Println("success");
http.ListenAndServe(":8000", nil)

Please help:)

Body:
Seems like there is typo. Should be .Username not .Password

pconfig := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",cfg.Host,cfg.Port,cfg.Password,cfg.Password,cfg.DBname)

Else, try make sure all the parameters tally with Postgres Connection

    Host:     "localhost", // where you host your Postgres server
    Port:     5432, // default port for Postgres
    Username: "postgres", // this is user credential to access of the database
    Password: "ellez2004", // corresponding password
    DBname:   "app", // the database schema name


问:
amChart 'countries visited' map - how to make mobile responsive
How can I make the 'countries visited' map mobile responsive? It shows fine on PC, but the map is off the page on a mobile/smartphone. You cant even slide the map over.

I got the HTML for the map from https://www.amcharts.com/visited_countries/

I'm a novice not a coder, so not sure if there is code that can be added to make the map mobile responsive. Is it possible?

答:
After some experimentation this is what worked for me. I used the video container CSS code from here which is used to make embedded videos responsive.
Then I edited the div line from amCharts from:

```
<p>To:</p>
<pre class="lang-html prettyprint-override"><code><div class="video-container" id="mapdiv" style="max-width: 775px; max-height: 450px;"></div>
</code>```

Hope this can work for you.

Body:
After some experimentation this is what worked for me. I used the video container CSS code from here which is used to make embedded videos responsive.
Then I edited the div line from amCharts from:

<div id="mapdiv" style="width: 775px; height: 450px;"></div>

To:

<div class="video-container" id="mapdiv" style="max-width: 775px; max-height: 450px;"></div>

Hope this can work for you.


问:
How to retrieve a random value from an array that has values separate by a new line
I am a complete newbie at JS and currently using it in a testing capacity along with the Karate framework to perform some UI testing. I am having the following problem:

There is a dropdown that has the following HTML:

<select class=id="CarId" name="CarId" aria-describedby="CarId-error" aria-invalid="false" xpath="1">
<option value="1">Mercedes</option>
<option value="2">BMW</option>
<option value="3">Lexus</option>
<option value="4">Honda</option>
<option value="5">Toyota</option>
<option value="6">VW</option>
</select>
```
<p>I used the following Karate method to get all text values under the dropdown:</p>
```def grabValues = scriptAll('#CarId', '_.textContent')
```
<p>Once printed, the array look like this:</p>
<pre class="lang-js prettyprint-override"><code>[
  "Mercedes\nBMW\nLexus\nHonda\nToyota\nVW\n"
]

console.log(Math.floor(Math.random() * (grabValues.length-1)))
</code>```

When printed, it keeps giving me 0.0. I am assuming this is because the array contains new lines vs comma delimitated? If so, how can I get rid of the new lines and replace with commas?

答:
What you want is to get the text from each <option>

def grabValues = scriptAll('#CarId option', '_.textContent')
```
<p>This will give you an array of text values like</p>
<pre class="lang-js prettyprint-override"><code>["Mercedes","BMW","Lexus","Honda","Toyota","VW"]
</code>```

To get a random index you would use

Math.floor(Math.random() * grabValues.length)
```

Body:
I am a complete newbie at JS and currently using it in a testing capacity along with the Karate framework to perform some UI testing. I am having the following problem:

There is a dropdown that has the following HTML:

<select class=id="CarId" name="CarId" aria-describedby="CarId-error" aria-invalid="false" xpath="1">
<option value="1">Mercedes</option>
<option value="2">BMW</option>
<option value="3">Lexus</option>
<option value="4">Honda</option>
<option value="5">Toyota</option>
<option value="6">VW</option>
</select>

I used the following Karate method to get all text values under the dropdown:

def grabValues = scriptAll('#CarId', '_.textContent')

Once printed, the array look like this:

[
  "Mercedes\nBMW\nLexus\nHonda\nToyota\nVW\n"
]

console.log(Math.floor(Math.random() * (grabValues.length-1)))

When printed, it keeps giving me 0.0. I am assuming this is because the array contains new lines vs comma delimitated? If so, how can I get rid of the new lines and replace with commas?

Body:
What you want is to get the text from each <option>

def grabValues = scriptAll('#CarId option', '_.textContent')

This will give you an array of text values like

["Mercedes","BMW","Lexus","Honda","Toyota","VW"]

To get a random index you would use

Math.floor(Math.random() * grabValues.length)


问:
How to scrape only clickable links in a loop with Scrapy and Selenium
I'm trying to scrape some info on tennis matches from a Javascript site using Scrapy and Selenium. The starting URLs are for pages that contain all the matches on a given date. The first task on each page is to make all the matches visible from behind some horizontal tabs - got this covered. The second task is to scrape the match pages that sit behind links that aren't present on the starting URL pages - a specific tag needs to be clicked.

I've found all these tags no problem and have a loop written that uses Selenium to click the tag and yields a Request after each iteration. The issue I'm having is that each time I click through on a link then the page changes and my lovely list of elements detaches itself from the DOM and I get a StaleElementReferenceException error. I understand why this happens but I'm struggling to come up with a solution.

Here's my code so far:

```<code>import datetime as dt
from dateutil.rrule import DAILY, rrule
from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess
from scrapy.http.response import Response
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

MATCHES_XPATH = "//span[@class='link sc-10gv6xe-4 eEAcym pointer']"
ELEMENT_TEST = "//span[@class='link sc-15d69aw-2 hhbGos']"

class ScraperS24(Spider):

    name = "scores24_scraper"

    custom_settings = {
        "USER_AGENT": "*",
        "LOG_LEVEL": "WARNING",
        "DOWNLOADER_MIDDLEWARES": {
            'scraper.polgara.middlewares.SeleniumMiddleware': 543,
        },
    }
    httperror_allowed_codes = [301]

    def __init__(self):
        dates = list(rrule(DAILY, dtstart=dt.datetime(2015, 1, 6), until=dt.datetime(2015, 1, 21)))
        self.start_urls = [f"https://scores24.live/en/tennis/{d.strftime('%Y-%m-%d')}" for d in dates]
        super().__init__()

    def parse(self, response: Response):
        print(f"Parsing date - {response.url}")
        driver = response.request.meta["driver"]
        tabs = driver.find_elements_by_xpath("//button[@class='hjlkds-7 khtDIT']")
        for t in tabs: driver.execute_script("arguments[0].click();", t)
        matches = driver.find_elements_by_xpath(MATCHES_XPATH)
        wait = WebDriverWait(driver, 20)
        for m in matches:
            driver.execute_script("arguments[0].click();", m)
            try:
                wait.until(EC.presence_of_element_located((By.XPATH, ELEMENT_TEST)))
            except TimeoutException:
                driver.back()
            else:
                url = str(driver.current_url)
                driver.back()
                yield Request(url, callback=self._parse_match)

    def _parse_match(self, response):
        print(f"Parsing match - {response.url}")

process = CrawlerProcess()
process.crawl(ScraperS24)
process.start()
</code>```

And the Selenium middleware:

```<code>class SeleniumMiddleware:

    @classmethod
    def from_crawler(cls, crawler):
        middleware = cls()
        crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
        crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
        return middleware

    def process_request(self, request: Request, spider: Spider):
        logger.debug(f"Selenium processing request - {request.url}")
        self.driver.get(request.url)
        request.meta.update({'driver': self.driver})
        return HtmlResponse(
            request.url,
            body=self.driver.page_source,
            encoding='utf-8',
            request=request,
        )

    def spider_opened(self, spider):
        options = webdriver.FirefoxOptions()
        options.add_argument("--headless")
        self.driver = webdriver.Firefox(
            options=options,
            executable_path=cn.GECKODRIVER_PATH,
        )

    def spider_closed(self, spider):
        self.driver.quit()
</code>```

I've tried adapting the loop using the answer here:

```<code>for idx, _ in enumerate(matches):
    matches = driver.find_elements_by_xpath(MATCHES_XPATH)
    driver.execute_script("arguments[0].click();", matches[idx])
    try:
        wait.until(EC.presence_of_element_located((By.XPATH, ELEMENT_TEST)))
    except TimeoutException:
        driver.back()
    else:
        url = str(driver.current_url)
        driver.back()
        yield Request(url, callback=self._parse_match)
</code>```

However, because Scrapy scrapes in parallel then the driver is very quickly used to load up a new starting URL page before the loop has finished and so the list indexing on matches gets screwed.

Any ideas on where I could go from here? Is there a way to for me to use the adapted loop and force Scrapy to finish scraping all the match tags on a starting URL page before moving onto the next URL? There are answers on how to do this but they rely on storing a list of URLs on each page - something I don't have the luxury of...

答:
The page you are trying to scrape does not need you to use Selenium because the data is already contained in the html of the page.

Most of the information on a match is available in the matches json object so you might not need to scrape the pages that follow depending on what information you want to obtain.

See below code that shows you how to parse the matches data directly from the html.

import scrapy
import datetime as dt
from dateutil.rrule import DAILY, rrule
import json
from scrapy.crawler import CrawlerProcess

class ScraperS24(scrapy.Spider):

    name = "scores24_scraper"

    custom_settings = {
        "USER_AGENT": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
    }

    def __init__(self):
        dates = list(rrule(DAILY, dtstart=dt.datetime(2015, 1, 6), until=dt.datetime(2015, 1, 6)))
        self.start_urls = [f"https://scores24.live/en/tennis/{d.strftime('%Y-%m-%d')}" for d in dates]
        super().__init__()

    def parse(self, response):
        # obtain the json response object
        data = response.xpath("//script[contains(text(),'window.__APP__STATE__=JSON.parse')]/text()").re_first(r"window\.__APP__STATE__=JSON\.parse\((.*)\);")
        data_json = json.loads(data)
        data_json = json.loads(data_json)
        tennis_data = data_json["matchFeed"]["_feed"]["tennis"] # this is a list

        for tournament in tennis_data:
            for match in tournament["matches"]:
                match_url = f"m-{match['slug']}"
                yield match # outputs the summary data on each match. Comment this line if following links to each match
                # to follow the links to each match uncomment the line below
                #yield response.follow(match_url, callback=self.parse_match)

    def parse_match(self, response):
        self.logger.info("Parsing match on url: " + response.url)
        # parse the match details here

if __name__ == '__main__':
    process = CrawlerProcess()
    process.crawl(ScraperS24)
    process.start()
```

If you run the scraper, you will obtain results similar to the below image for each match.

Body:
I'm trying to scrape some info on tennis matches from a Javascript site using Scrapy and Selenium. The starting URLs are for pages that contain all the matches on a given date. The first task on each page is to make all the matches visible from behind some horizontal tabs - got this covered. The second task is to scrape the match pages that sit behind links that aren't present on the starting URL pages - a specific tag needs to be clicked.

I've found all these tags no problem and have a loop written that uses Selenium to click the tag and yields a Request after each iteration. The issue I'm having is that each time I click through on a link then the page changes and my lovely list of elements detaches itself from the DOM and I get a StaleElementReferenceException error. I understand why this happens but I'm struggling to come up with a solution.

Here's my code so far:

import datetime as dt
from dateutil.rrule import DAILY, rrule
from scrapy import Spider, Request
from scrapy.crawler import CrawlerProcess
from scrapy.http.response import Response
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

MATCHES_XPATH = "//span[@class='link sc-10gv6xe-4 eEAcym pointer']"
ELEMENT_TEST = "//span[@class='link sc-15d69aw-2 hhbGos']"

class ScraperS24(Spider):

    name = "scores24_scraper"

    custom_settings = {
        "USER_AGENT": "*",
        "LOG_LEVEL": "WARNING",
        "DOWNLOADER_MIDDLEWARES": {
            'scraper.polgara.middlewares.SeleniumMiddleware': 543,
        },
    }
    httperror_allowed_codes = [301]

    def __init__(self):
        dates = list(rrule(DAILY, dtstart=dt.datetime(2015, 1, 6), until=dt.datetime(2015, 1, 21)))
        self.start_urls = [f"https://scores24.live/en/tennis/{d.strftime('%Y-%m-%d')}" for d in dates]
        super().__init__()

    def parse(self, response: Response):
        print(f"Parsing date - {response.url}")
        driver = response.request.meta["driver"]
        tabs = driver.find_elements_by_xpath("//button[@class='hjlkds-7 khtDIT']")
        for t in tabs: driver.execute_script("arguments[0].click();", t)
        matches = driver.find_elements_by_xpath(MATCHES_XPATH)
        wait = WebDriverWait(driver, 20)
        for m in matches:
            driver.execute_script("arguments[0].click();", m)
            try:
                wait.until(EC.presence_of_element_located((By.XPATH, ELEMENT_TEST)))
            except TimeoutException:
                driver.back()
            else:
                url = str(driver.current_url)
                driver.back()
                yield Request(url, callback=self._parse_match)

    def _parse_match(self, response):
        print(f"Parsing match - {response.url}")

process = CrawlerProcess()
process.crawl(ScraperS24)
process.start()

And the Selenium middleware:

class SeleniumMiddleware:

    @classmethod
    def from_crawler(cls, crawler):
        middleware = cls()
        crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
        crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
        return middleware

    def process_request(self, request: Request, spider: Spider):
        logger.debug(f"Selenium processing request - {request.url}")
        self.driver.get(request.url)
        request.meta.update({'driver': self.driver})
        return HtmlResponse(
            request.url,
            body=self.driver.page_source,
            encoding='utf-8',
            request=request,
        )

    def spider_opened(self, spider):
        options = webdriver.FirefoxOptions()
        options.add_argument("--headless")
        self.driver = webdriver.Firefox(
            options=options,
            executable_path=cn.GECKODRIVER_PATH,
        )

    def spider_closed(self, spider):
        self.driver.quit()

I've tried adapting the loop using the answer here:

for idx, _ in enumerate(matches):
    matches = driver.find_elements_by_xpath(MATCHES_XPATH)
    driver.execute_script("arguments[0].click();", matches[idx])
    try:
        wait.until(EC.presence_of_element_located((By.XPATH, ELEMENT_TEST)))
    except TimeoutException:
        driver.back()
    else:
        url = str(driver.current_url)
        driver.back()
        yield Request(url, callback=self._parse_match)

However, because Scrapy scrapes in parallel then the driver is very quickly used to load up a new starting URL page before the loop has finished and so the list indexing on matches gets screwed.

Any ideas on where I could go from here? Is there a way to for me to use the adapted loop and force Scrapy to finish scraping all the match tags on a starting URL page before moving onto the next URL? There are answers on how to do this but they rely on storing a list of URLs on each page - something I don't have the luxury of...

Body:
The page you are trying to scrape does not need you to use Selenium because the data is already contained in the html of the page.

Most of the information on a match is available in the matches json object so you might not need to scrape the pages that follow depending on what information you want to obtain.

See below code that shows you how to parse the matches data directly from the html.

import scrapy
import datetime as dt
from dateutil.rrule import DAILY, rrule
import json
from scrapy.crawler import CrawlerProcess

class ScraperS24(scrapy.Spider):

    name = "scores24_scraper"

    custom_settings = {
        "USER_AGENT": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36",
    }

    def __init__(self):
        dates = list(rrule(DAILY, dtstart=dt.datetime(2015, 1, 6), until=dt.datetime(2015, 1, 6)))
        self.start_urls = [f"https://scores24.live/en/tennis/{d.strftime('%Y-%m-%d')}" for d in dates]
        super().__init__()

    def parse(self, response):
        # obtain the json response object
        data = response.xpath("//script[contains(text(),'window.__APP__STATE__=JSON.parse')]/text()").re_first(r"window\.__APP__STATE__=JSON\.parse\((.*)\);")
        data_json = json.loads(data)
        data_json = json.loads(data_json)
        tennis_data = data_json["matchFeed"]["_feed"]["tennis"] # this is a list

        for tournament in tennis_data:
            for match in tournament["matches"]:
                match_url = f"m-{match['slug']}"
                yield match # outputs the summary data on each match. Comment this line if following links to each match
                # to follow the links to each match uncomment the line below
                #yield response.follow(match_url, callback=self.parse_match)

    def parse_match(self, response):
        self.logger.info("Parsing match on url: " + response.url)
        # parse the match details here

if __name__ == '__main__':
    process = CrawlerProcess()
    process.crawl(ScraperS24)
    process.start()

If you run the scraper, you will obtain results similar to the below image for each match.


问:
After upgrading to gradle 7.x generating two war files
After upgrading from gradle 5.x to 7.x, two war files generating.

Below are the 2 war file names

```<code>test-app-1.0.0.war
test-app-1.0.0-plain.war
</code>```

below is gradle plugin and task used:

```<code>plugins {
    id 'war'
}

bootWar {
    launchScript()
    manifest {
        attributes 'Implementation-Version':  archiveVersion
    }
}

</code>```

I want to generate only test-app-1.0.0.war. How to fix this?

答:
Based on the reference plain jar - stackoverflow:

Changed build.gradle like below

```<code>war {
    enabled = false
}

bootWar {
    enabled = true
    launchScript()
    manifest {
        attributes 'Implementation-Version':  archiveVersion
    }
}
</code>```

Now it's generating only test-app-1.0.0.war

Body:
After upgrading from gradle 5.x to 7.x, two war files generating.

Below are the 2 war file names

test-app-1.0.0.war
test-app-1.0.0-plain.war

below is gradle plugin and task used:

plugins {
    id 'war'
}

bootWar {
    launchScript()
    manifest {
        attributes 'Implementation-Version':  archiveVersion
    }
}

I want to generate only test-app-1.0.0.war. How to fix this?

Body:
Based on the reference plain jar - stackoverflow:

Changed build.gradle like below

war {
    enabled = false
}

bootWar {
    enabled = true
    launchScript()
    manifest {
        attributes 'Implementation-Version':  archiveVersion
    }
}

Now it's generating only test-app-1.0.0.war