## Step 1: Define the variables and their attributes
We have four variables: 'hours worked by Bill', 'hours worked by Hank', 'hours worked by Bobby', and 'hours worked by John'. Let's denote these as $x_B$, $x_H$, $x_{Bo}$, and $x_J$ respectively. The attributes for each variable are given in the resource dictionary.

## 2: Formulate the objective function
The objective function to maximize is $9x_B + 3x_H + 2x_{Bo} + 2x_J$.

## 3: List all constraints
1. $6x_B \geq 31$,
2. $6x_B + 7x_{Bo} \geq 31$,
3. $6x_B + 6x_H + 11x_J \geq 37$,
4. $6x_B + 6x_H + 7x_{Bo} \geq 37$,
5. $9x_H + 18x_{Bo} \geq 17$,
6. $9x_H + 12x_J \geq 20$,
7. $8x_B + 9x_H \geq 27$,
8. $18x_{Bo} + 12x_J \geq 19$,
9. $7x_B + x_{Bo} + 13x_J \geq 26$,
10. $7x_B + 4x_H + x_{Bo} \geq 26$,
11. $7x_B + x_{Bo} + 13x_J \geq 27$,
12. $7x_B + 4x_H + x_{Bo} \geq 27$,
13. $7x_{Bo} + 11x_J \leq 99$,
14. $6x_B + 11x_J \leq 52$,
15. $6x_B + 7x_{Bo} \leq 118$,
16. $6x_B + 7x_{Bo} + 11x_J \leq 60$,
17. $6x_B + 6x_H + 7x_{Bo} + 11x_J \leq 60$,
18. $8x_B + 18x_{Bo} \leq 104$,
19. $9x_H + 18x_{Bo} \leq 63$,
20. $8x_B + 12x_J \leq 34$,
21. $8x_B + 9x_H \leq 72$,
22. $8x_B + 9x_H + 18x_{Bo} + 12x_J \leq 72$,
23. $7x_B + 4x_H \leq 64$,
24. $7x_B + x_{Bo} \leq 71$,
25. $7x_B + 13x_J \leq 106$,
26. $4x_H + 13x_J \leq 29$,
27. $7x_B + 4x_H + x_{Bo} + 13x_J \leq 29$.

## 4: Implement the problem in Gurobi
```python
import gurobi

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

    # Define the variables
    x_B = model.addVar(name="hours_worked_by_Bill", lb=0)
    x_H = model.addVar(name="hours_worked_by_Hank", lb=0)
    x_Bo = model.addVar(name="hours_worked_by_Bobby", lb=0)
    x_J = model.addVar(name="hours_worked_by_John", lb=0)

    # Define the objective function
    model.setObjective(9 * x_B + 3 * x_H + 2 * x_Bo + 2 * x_J, gurobi.GRB.MAXIMIZE)

    # Add constraints
    model.addConstr(6 * x_B >= 31)
    model.addConstr(6 * x_B + 7 * x_Bo >= 31)
    model.addConstr(6 * x_B + 6 * x_H + 11 * x_J >= 37)
    model.addConstr(6 * x_B + 6 * x_H + 7 * x_Bo >= 37)
    model.addConstr(9 * x_H + 18 * x_Bo >= 17)
    model.addConstr(9 * x_H + 12 * x_J >= 20)
    model.addConstr(8 * x_B + 9 * x_H >= 27)
    model.addConstr(18 * x_Bo + 12 * x_J >= 19)
    model.addConstr(7 * x_B + x_Bo + 13 * x_J >= 26)
    model.addConstr(7 * x_B + 4 * x_H + x_Bo >= 26)
    model.addConstr(7 * x_B + x_Bo + 13 * x_J >= 27)
    model.addConstr(7 * x_B + 4 * x_H + x_Bo >= 27)
    model.addConstr(7 * x_Bo + 11 * x_J <= 99)
    model.addConstr(6 * x_B + 11 * x_J <= 52)
    model.addConstr(6 * x_B + 7 * x_Bo <= 118)
    model.addConstr(6 * x_B + 7 * x_Bo + 11 * x_J <= 60)
    model.addConstr(6 * x_B + 6 * x_H + 7 * x_Bo + 11 * x_J <= 60)
    model.addConstr(8 * x_B + 18 * x_Bo <= 104)
    model.addConstr(9 * x_H + 18 * x_Bo <= 63)
    model.addConstr(8 * x_B + 12 * x_J <= 34)
    model.addConstr(8 * x_B + 9 * x_H <= 72)
    model.addConstr(8 * x_B + 9 * x_H + 18 * x_Bo + 12 * x_J <= 72)
    model.addConstr(7 * x_B + 4 * x_H <= 64)
    model.addConstr(7 * x_B + x_Bo <= 71)
    model.addConstr(7 * x_B + 13 * x_J <= 106)
    model.addConstr(4 * x_H + 13 * x_J <= 29)
    model.addConstr(7 * x_B + 4 * x_H + x_Bo + 13 * x_J <= 29)

    # Optimize the model
    model.optimize()

    # Print the solution
    if model.status == gurobi.GRB.OPTIMAL:
        print("Optimal solution found.")
        print(f"Hours worked by Bill: {x_B.varValue}")
        print(f"Hours worked by Hank: {x_H.varValue}")
        print(f"Hours worked by Bobby: {x_Bo.varValue}")
        print(f"Hours worked by John: {x_J.varValue}")
        print(f"Objective: {model.objVal}")
    else:
        print("No optimal solution found.")

optimize_problem()
```