# Web & Network

## Packets
<iframe style="width:100%;aspect-ratio:16/9" src="https://www.youtube.com/embed/yYst7puZXjw?si=JUKK_o3AnfoATGbD&amp;controls=0&amp;start=224" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## TCP/IP 
- Two set of protocols that we decided a while ago to standardize information transfer

## IP
### IP Address
![](attachment/6d5329217a8902c6b252f01b07f0b140.png)

### IP Diagram
![](attachment/66831f25ecd6a8994e6d338cff2568af.png)

### Remarks
- Now, I know where your machine is on the internet, how do I get what I want? Just knowing your home alone doesn't really allow us to communicate.

## TCP
### Ports
- Pretty much where your process, or program runs 

### TCP Diagram
![](attachment/785e853f8871f4abb2908de6c86e8d32.png)

## Notes
- The real internet has a bunch more complicated stuff & more but I won't talk about it here.
- However I will provided the rationale:
	- DNS: People don't like remembering numbers
	- DHCP: Every devices has an IP address, but what IP address exactly?
	- ... 

## Postman Demo
<iframe src="http://100.88.60.127:5000/dashboard" width="100%" height="500"
        style="border:none;" id="cs50-frame"></iframe>
<script>
  setInterval(() => {
    const f = document.getElementById('cs50-frame');
    f.src = f.src;
  }, 3000);
</script>

# Data 
## Flatfile database
- As you have likely seen before, data can often be described in patterns of columns and rows.
- Spreadsheets like those created in Microsoft Excel and Google Sheets can be outputted to a `csv` or _comma-separated values_ file.
- If you look at a `csv` file, you’ll notice that the file is flat in that all of our data is stored in a single table represented by a text file. We call this form of data a _flat-file database_.

## Relational Database
- Remember, most of what we want when we do data work is to get the rows based on certain constraints on the columns.
- This works great until you have data points that have relationship with each other. 
- The most intuitive insight to understand this is to understand each row is supposed to represent an emergence of what the columns is. 
	- Or to think of each table will correspond to one class of objects.

### Example - Problem
| customer_id | customer_name | email | city | order_id | product | quantity | price | 
|---|---|---|---|---|---|---|---| 
| 1 | Minh | minh@mail.com | Hanoi | 101 | Laptop | 1 | 999 | 
| 1 | Minh | minh@mail.com | Hanoi | 102 | Mouse | 2 | 25 |
| 1 | Minh | minh@mail.com | Hanoi | 103 | Keyboard | 1 | 75 | 
| 2 | Linh | linh@mail.com | HCMC | 104 | Monitor | 1 | 350 |

### Example - Solution
**customers** 

| customer_id | name | email | city |
|---|---|---|---| 
| 1 | Minh | minh@mail.com | Hanoi | 
| 2 | Linh | linh@mail.com | HCMC | 

**orders** 

| order_id | customer_id | product | quantity | price | 
|---|---|---|---|---| 
| 101 | 1 | Laptop | 1 | 999 | 
| 102 | 1 | Mouse | 2 | 25 | 
| 103 | 1 | Keyboard | 1 | 75 | 
| 104 | 2 | Monitor | 1 | 350 |

## SQLite & Python 
```python
# Searches database for popularity of a problem

from cs50 import SQL

# Open database
db = SQL("sqlite:///favorites.db")

# Prompt user for favorite
favorite = input("Favorite: ")

# Search for title
rows = db.execute("SELECT COUNT(*) AS n FROM favorites WHERE problem = ?", favorite)

# Get first (and only) row
row = rows[0]

# Print popularity
print(row["n"])
```
### Model 
```python
# Searches database for popularity of a problem

from cs50 import SQL

# Open database
db = SQL("sqlite:///favorites.db") <-

# Prompt user for favorite
favorite = input("Favorite: ")

# Search for title
rows = db.execute("SELECT COUNT(*) AS n FROM favorites WHERE problem = ?", favorite) <-

# Get first (and only) row
row = rows[0] 

# Print popularity
print(row["n"])
```

### Controller
```python
# Searches database for popularity of a problem

from cs50 import SQL

# Open database
db = SQL("sqlite:///favorites.db") 

# Prompt user for favorite
favorite = input("Favorite: ") <-

# Search for title
rows = db.execute("SELECT COUNT(*) AS n FROM favorites WHERE problem = ?", favorite) <-

# Get first (and only) row
row = rows[0] <-

# Print popularity
print(row["n"]) <-
```
## MongoDB & Java
### Model
```java
@Document(collection = "favorites")
public class Favorite {
    @Id
    private String id;
    private String problem;
    // getters, setters, constructors
}
```

```java
public interface FavoriteRepository extends MongoRepository<Favorite, String> {
    long countByProblem(String problem);
}
```
### Controller 
```java
@Component
public class FavoriteSearchRunner implements CommandLineRunner {

    private final FavoriteRepository favoriteRepository;

    public FavoriteSearchRunner(FavoriteRepository favoriteRepository) {
        this.favoriteRepository = favoriteRepository;
    }

    @Override
    public void run(String... args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Favorite: ");
        String favorite = scanner.nextLine();

        long count = favoriteRepository.countByProblem(favorite);
        System.out.println(count);
    }
}
```
# Interface
## Flask & Web
```python
# Implements a registration form, storing registrants in a SQLite database, with support for multiple sports and deregistration

from cs50 import SQL
from flask import Flask, redirect, render_template, request

app = Flask(__name__)

db = SQL("sqlite:///froshims.db")

SPORTS = [
    "Basketball",
    "Soccer",
    "Ultimate Frisbee"
]


@app.route("/")
def index():
    return render_template("index.html", sports=SPORTS)


@app.route("/deregister", methods=["POST"])
def deregister():

    # Forget registrant
    id = request.form.get("id")
    if id:
        db.execute("DELETE FROM registrants WHERE id = ?", id)
    return redirect("/registrants")


@app.route("/register", methods=["POST"])
def register():

    # Validate name
    name = request.form.get("name")
    if not name:
        return render_template("error.html", message="Missing name")

    # Validate sports
    sports = request.form.getlist("sport")
    if not sports:
        return render_template("error.html", message="Missing sport")
    for sport in sports:
        if sport not in SPORTS:
            return render_template("error.html", message="Invalid sport")

    # Remember registrant
    for sport in sports:
        db.execute("INSERT INTO registrants (name, sport) VALUES(?, ?)", name, sport)

    # Confirm registration
    return redirect("/registrants")


@app.route("/registrants")
def registrants():
    registrants = db.execute("SELECT * FROM registrants")
    return render_template("registrants.html", registrants=registrants)
```
## JavaFX & GUI
### Model
```java
public class Registrant {
    private int id;
    private String name;
    private String sport;

    public Registrant(int id, String name, String sport) {
        this.id = id;
        this.name = name;
        this.sport = sport;
    }

    public int getId()     { return id; }
    public String getName()  { return name; }
    public String getSport() { return sport; }
}
```

```java
public class DatabaseManager {
    private static final String URL = "jdbc:sqlite:froshims.db";

    public List<Registrant> getAllRegistrants() {
        List<Registrant> list = new ArrayList<>();
        String sql = "SELECT * FROM registrants";

        try (Connection conn = DriverManager.getConnection(URL);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {

            while (rs.next()) {
                list.add(new Registrant(
                    rs.getInt("id"),
                    rs.getString("name"),
                    rs.getString("sport")
                ));
            }
        } catch (SQLException e) { e.printStackTrace(); }
        return list;
    }

    public void addRegistrant(String name, String sport) {
        String sql = "INSERT INTO registrants (name, sport) VALUES (?, ?)";
        try (Connection conn = DriverManager.getConnection(URL);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setString(1, name);
            ps.setString(2, sport);
            ps.executeUpdate();
        } catch (SQLException e) { e.printStackTrace(); }
    }

    public void deleteRegistrant(int id) {
        String sql = "DELETE FROM registrants WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(URL);
             PreparedStatement ps = conn.prepareStatement(sql)) {
            ps.setInt(1, id);
            ps.executeUpdate();
        } catch (SQLException e) { e.printStackTrace(); }
    }
}
```
### View
```java
<VBox xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.froshims.controller.RegisterController"
      spacing="10" padding="20">

    <Label text="Name:" />
    <TextField fx:id="nameField" promptText="Enter your name" />

    <Label text="Sports:" />
    <CheckBox fx:id="basketballBox" text="Basketball" />
    <CheckBox fx:id="soccerBox"     text="Soccer" />
    <CheckBox fx:id="frisbeeBox"    text="Ultimate Frisbee" />

    <Button text="Register" onAction="#handleRegister" />
    <Button text="View Registrants" onAction="#handleViewRegistrants" />
</VBox>
```

```java
<VBox xmlns:fx="http://javafx.com/fxml"
      fx:controller="com.froshims.controller.RegistrantsController"
      spacing="10" padding="20">

    <TableView fx:id="registrantsTable">
        <columns>
            <TableColumn fx:id="nameColumn"  text="Name" />
            <TableColumn fx:id="sportColumn" text="Sport" />
        </columns>
    </TableView>

    <Button text="Deregister Selected" onAction="#handleDeregister" />
</VBox>
```
### Controller
```java
public class RegisterController {

    @FXML private TextField nameField;
    @FXML private CheckBox basketballBox, soccerBox, frisbeeBox;

    private final DatabaseManager db = new DatabaseManager();

    // mirrors Flask's @app.route("/register", methods=["POST"])
    @FXML
    private void handleRegister() {
        String name = nameField.getText().trim();

        // Validate name — mirrors: if not name: render_template("error.html")
        if (name.isEmpty()) {
            showError("Missing name");
            return;
        }

        // Collect checked sports — mirrors: sports = request.form.getlist("sport")
        List<String> selected = new ArrayList<>();
        if (basketballBox.isSelected()) selected.add("Basketball");
        if (soccerBox.isSelected())     selected.add("Soccer");
        if (frisbeeBox.isSelected())    selected.add("Ultimate Frisbee");

        if (selected.isEmpty()) {
            showError("Missing sport");
            return;
        }

        // Hand off to Model — mirrors: db.execute("INSERT INTO ...")
        for (String sport : selected) {
            db.addRegistrant(name, sport);
        }

        // Navigate away — mirrors: return redirect("/registrants")
        loadRegistrantsView();
    }

    private void showError(String message) {
        Alert alert = new Alert(Alert.AlertType.ERROR, message);
        alert.showAndWait();
    }
}
```

```java
public class RegistrantsController {

    @FXML private TableView<Registrant> registrantsTable;
    @FXML private TableColumn<Registrant, String> nameColumn;
    @FXML private TableColumn<Registrant, String> sportColumn;

    private final DatabaseManager db = new DatabaseManager();

    // mirrors Flask's @app.route("/registrants") → registrants()
    @FXML
    public void initialize() {
        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        sportColumn.setCellValueFactory(new PropertyValueFactory<>("sport"));

        // Hand Model data to View — mirrors: render_template("registrants.html", registrants=registrants)
        List<Registrant> data = db.getAllRegistrants();
        registrantsTable.setItems(FXCollections.observableArrayList(data));
    }

    // mirrors Flask's @app.route("/deregister", methods=["POST"])
    @FXML
    private void handleDeregister() {
        Registrant selected = registrantsTable.getSelectionModel().getSelectedItem();
        if (selected != null) {
            db.deleteRegistrant(selected.getId());  // tells Model
            initialize();                           // refreshes View
        }
    }
}
```
# Project Management (Integration)
## Build Systems
### Imperative
### Declarative
## Tests
## CI/CD
# Work
