## Problem Description and Symbolic Representation

The problem can be broken down into the following components:

- **Variables:**
  - $x_1$: orders of fries
  - $x_2$: orders of onion rings

- **Objective Function:** Maximize profit $= 4x_1 + 5x_2$

- **Constraints:**
  1. $x_1 \geq 20$ (at least 20 orders of fries)
  2. $x_1 \leq 50$ (at most 50 orders of fries)
  3. $x_2 \geq 10$ (at least 10 orders of onion rings)
  4. $x_2 \leq 40$ (at most 40 orders of onion rings)
  5. $x_1 + x_2 \leq 50$ (total orders cannot exceed 50)

## Symbolic Representation

```json
{
  'sym_variables': [('x1', 'orders of fries'), ('x2', 'orders of onion rings')],
  'objective_function': '4*x1 + 5*x2',
  'constraints': [
    'x1 >= 20',
    'x1 <= 50',
    'x2 >= 10',
    'x2 <= 40',
    'x1 + x2 <= 50'
  ]
}
```

## Gurobi Code

```python
import gurobi

def solve_food_truck_problem():
    # Create a new model
    m = gurobi.Model()

    # Define variables
    x1 = m.addVar(lb=20, ub=50, name="fries")
    x2 = m.addVar(lb=10, ub=40, name="onion_rings")

    # Objective function: Maximize profit
    m.setObjective(4*x1 + 5*x2, gurobi.GRB.MAXIMIZE)

    # Constraints
    m.addConstr(x1 + x2 <= 50, name="total_orders")

    # Optimize
    m.optimize()

    # Print solution
    if m.status == gurobi.GRB.OPTIMAL:
        print(f"Optimal solution: {x1.varName} = {x1.x}, {x2.varName} = {x2.x}")
        print(f"Max Profit: {m.objVal}")
    else:
        print("No optimal solution found")

solve_food_truck_problem()
```