```json
{
  "sym_variables": [
    ("x0", "hours worked by Hank"),
    ("x1", "hours worked by Ringo"),
    ("x2", "hours worked by John"),
    ("x3", "hours worked by Mary")
  ],
  "objective_function": "5.51 * x0 + 6.01 * x1 + 3.55 * x2 + 3.47 * x3",
  "constraints": [
    "2 * x0 + 11 * x1 >= 33",
    "15 * x2 + 17 * x3 >= 21",
    "11 * x1 + 17 * x3 >= 18",
    "2 * x0 + 11 * x1 + 17 * x3 >= 29",
    "2 * x0 + 11 * x1 + 15 * x2 >= 29",
    "11 * x1 + 15 * x2 + 17 * x3 >= 29",
    "2 * x0 + 11 * x1 + 17 * x3 >= 24",
    "2 * x0 + 11 * x1 + 15 * x2 >= 24",
    "11 * x1 + 15 * x2 + 17 * x3 >= 24",
    "2 * x0 + 11 * x1 + 17 * x3 >= 21",
    "2 * x0 + 11 * x1 + 15 * x2 >= 21",
    "11 * x1 + 15 * x2 + 17 * x3 >= 21",
    "8 * x1 + 1 * x2 + 23 * x3 >= 28",
    "13 * x1 + 14 * x2 >= 18",
    "6 * x0 + 23 * x3 >= 29",
    "14 * x2 + 23 * x3 >= 32",
    "6 * x0 + 14 * x2 + 23 * x3 >= 36",
    "2 * x0 + 11 * x1 <= 83",
    "15 * x2 + 17 * x3 <= 86",
    "2 * x0 + 15 * x2 <= 147",
    "11 * x1 + 17 * x3 <= 50",
    "2 * x0 + 17 * x3 <= 67",
    "2 * x0 + 11 * x1 + 15 * x2 + 17 * x3 <= 67",
    "8 * x1 + 1 * x2 <= 185",
    "1 * x2 + 23 * x3 <= 85",
    "8 * x1 + 23 * x3 <= 185",
    "14 * x0 + 1 * x2 <= 142",
    "14 * x0 + 8 * x1 <= 159",
    "14 * x0 + 8 * x1 + 1 * x2 + 23 * x3 <= 159",
    "14 * x2 + 23 * x3 <= 71",
    "6 * x0 + 23 * x3 <= 178",
    "6 * x0 + 14 * x2 <= 187",
    "13 * x1 + 23 * x3 <= 136",
    "6 * x0 + 13 * x1 <= 93",
    "13 * x1 + 14 * x2 + 23 * x3 <= 127",
    "6 * x0 + 13 * x1 + 14 * x2 <= 121",
    "6 * x0 + 13 * x1 + 23 * x3 <= 58",
    "6 * x0 + 13 * x1 + 14 * x2 + 23 * x3 <= 58",
    "x0 >= 0",
    "x1 >= 0",
    "x2 >= 0",
    "x3 >= 0"
  ]
}
```

```python
import gurobipy as gp

# Create a new model
model = gp.Model("WorkOptimization")

# Create variables
hank = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="hank")
ringo = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="ringo")
john = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="john")
mary = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="mary")


# Set objective function
model.setObjective(5.51 * hank + 6.01 * ringo + 3.55 * john + 3.47 * mary, gp.GRB.MAXIMIZE)

# Add constraints
model.addConstr(2 * hank + 11 * ringo >= 33)
model.addConstr(15 * john + 17 * mary >= 21)
model.addConstr(11 * ringo + 17 * mary >= 18)
model.addConstr(2 * hank + 11 * ringo + 17 * mary >= 29)
model.addConstr(2 * hank + 11 * ringo + 15 * john >= 29)
model.addConstr(11 * ringo + 15 * john + 17 * mary >= 29)
model.addConstr(2 * hank + 11 * ringo + 17 * mary >= 24)
model.addConstr(2 * hank + 11 * ringo + 15 * john >= 24)
model.addConstr(11 * ringo + 15 * john + 17 * mary >= 24)
model.addConstr(2 * hank + 11 * ringo + 17 * mary >= 21)
model.addConstr(2 * hank + 11 * ringo + 15 * john >= 21)
model.addConstr(11 * ringo + 15 * john + 17 * mary >= 21)
model.addConstr(8 * ringo + 1 * john + 23 * mary >= 28)
model.addConstr(13 * ringo + 14 * john >= 18)
model.addConstr(6 * hank + 23 * mary >= 29)
model.addConstr(14 * john + 23 * mary >= 32)
model.addConstr(6 * hank + 14 * john + 23 * mary >= 36)
model.addConstr(2 * hank + 11 * ringo <= 83)
model.addConstr(15 * john + 17 * mary <= 86)
model.addConstr(2 * hank + 15 * john <= 147)
model.addConstr(11 * ringo + 17 * mary <= 50)
model.addConstr(2 * hank + 17 * mary <= 67)
model.addConstr(2 * hank + 11 * ringo + 15 * john + 17 * mary <= 67)
model.addConstr(8 * ringo + 1 * john <= 185)
model.addConstr(1 * john + 23 * mary <= 85)
model.addConstr(8 * ringo + 23 * mary <= 185)
model.addConstr(14 * hank + 1 * john <= 142)
model.addConstr(14 * hank + 8 * ringo <= 159)
model.addConstr(14 * hank + 8 * ringo + 1 * john + 23 * mary <= 159)
model.addConstr(14 * john + 23 * mary <= 71)
model.addConstr(6 * hank + 23 * mary <= 178)
model.addConstr(6 * hank + 14 * john <= 187)
model.addConstr(13 * ringo + 23 * mary <= 136)
model.addConstr(6 * hank + 13 * ringo <= 93)
model.addConstr(13 * ringo + 14 * john + 23 * mary <= 127)
model.addConstr(6 * hank + 13 * ringo + 14 * john <= 121)
model.addConstr(6 * hank + 13 * ringo + 23 * mary <= 58)
model.addConstr(6 * hank + 13 * ringo + 14 * john + 23 * mary <= 58)


# Optimize model
model.optimize()

# Print results
if model.status == gp.GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Hank: {hank.x}")
    print(f"Ringo: {ringo.x}")
    print(f"John: {john.x}")
    print(f"Mary: {mary.x}")
    print(f"Objective value: {model.objVal}")
elif model.status == gp.GRB.INFEASIBLE:
    print("Model is infeasible.")
else:
    print(f"Optimization terminated with status {model.status}")

```