```json
{
  "sym_variables": [
    ("x0", "hours worked by Bill"),
    ("x1", "hours worked by John")
  ],
  "objective_function": "4.03*x0 + 7.68*x1",
  "constraints": [
    "6.44*x0 + 5.84*x1 >= 5",
    "2.16*x0 + 2.06*x1 >= 39",
    "4.71*x0 + 2.29*x1 >= 7",
    "4*x0 - 7*x1 >= 0",
    "6.44*x0 + 5.84*x1 <= 13",
    "2.16*x0 + 2.06*x1 <= 78",
    "4.71*x0 + 2.29*x1 <= 15"
  ]
}
```

```python
import gurobipy as gp

try:
    # Create a new model
    model = gp.Model("resource_allocation")

    # Create variables
    x0 = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="hours_worked_by_Bill")
    x1 = model.addVar(lb=0, vtype=gp.GRB.CONTINUOUS, name="hours_worked_by_John")


    # Set objective function
    model.setObjective(4.03 * x0 + 7.68 * x1, gp.GRB.MAXIMIZE)

    # Add constraints
    model.addConstr(6.44 * x0 + 5.84 * x1 >= 5, "organization_score_min")
    model.addConstr(2.16 * x0 + 2.06 * x1 >= 39, "productivity_rating_min")
    model.addConstr(4.71 * x0 + 2.29 * x1 >= 7, "computer_competence_min")
    model.addConstr(4 * x0 - 7 * x1 >= 0, "bill_john_ratio")
    model.addConstr(6.44 * x0 + 5.84 * x1 <= 13, "organization_score_max")
    model.addConstr(2.16 * x0 + 2.06 * x1 <= 78, "productivity_rating_max")
    model.addConstr(4.71 * x0 + 2.29 * x1 <= 15, "computer_competence_max")


    # Optimize model
    model.optimize()

    if model.status == gp.GRB.OPTIMAL:
        print('Obj: %g' % model.objVal)
        print('hours worked by Bill:', x0.x)
        print('hours worked by John:', x1.x)
    elif model.status == gp.GRB.INFEASIBLE:
        print('The model is infeasible.')
    else:
        print('Optimization ended with status %d' % model.status)


except gp.GurobiError as e:
    print('Error code ' + str(e.errno) + ': ' + str(e))

except AttributeError:
    print('Encountered an attribute error')
```