```python
from gurobipy import Model, GRB

# Create a new model
model = Model("Work Hour Optimization")

# Create variables
bobby_hours = model.addVar(vtype=GRB.CONTINUOUS, name="bobby_hours")
dale_hours = model.addVar(vtype=GRB.CONTINUOUS, name="dale_hours")
paul_hours = model.addVar(vtype=GRB.INTEGER, name="paul_hours")
john_hours = model.addVar(vtype=GRB.INTEGER, name="john_hours")

# Set objective function
model.setObjective(2 * bobby_hours + 5 * dale_hours + 7 * paul_hours + 3 * john_hours, GRB.MINIMIZE)

# Add constraints

# Likelihood to quit index
model.addConstr(2 * bobby_hours + 5 * john_hours >= 20)
model.addConstr(3 * paul_hours + 5 * john_hours >= 16)
model.addConstr(2 * bobby_hours + 5 * dale_hours + 3 * paul_hours + 5 * john_hours >= 16)
model.addConstr(5 * dale_hours + 3 * paul_hours <= 69)
model.addConstr(2 * bobby_hours + 5 * john_hours <= 87)
model.addConstr(5 * dale_hours + 3 * paul_hours + 5 * john_hours <= 24)
model.addConstr(2 * bobby_hours + 5 * dale_hours + 3 * paul_hours <= 39)
model.addConstr(2 * bobby_hours + 5 * dale_hours + 5 * john_hours <= 64)


# Work quality rating
model.addConstr(3 * dale_hours + 2 * paul_hours >= 22)
model.addConstr(3 * dale_hours + 5 * john_hours >= 29)
model.addConstr(2 * bobby_hours + 5 * john_hours >= 29)
model.addConstr(2 * bobby_hours + 2 * paul_hours >= 29)
model.addConstr(2 * bobby_hours + 3 * dale_hours + 2 * paul_hours + 5 * john_hours >= 29)
model.addConstr(3 * dale_hours + 2 * paul_hours <= 36)
model.addConstr(2 * bobby_hours + 2 * paul_hours <= 71)
model.addConstr(2 * bobby_hours + 2 * paul_hours + 5 * john_hours <= 105)
model.addConstr(3 * dale_hours + 2 * paul_hours + 5 * john_hours <= 83)
model.addConstr(2 * bobby_hours + 3 * dale_hours + 5 * john_hours <= 85)
model.addConstr(2 * bobby_hours + 3 * dale_hours + 2 * paul_hours <= 47)

# Organization score
model.addConstr(4 * bobby_hours + 5 * paul_hours >= 8)
model.addConstr(4 * bobby_hours + 3 * dale_hours >= 7)
model.addConstr(3 * dale_hours + 2 * john_hours >= 9)
model.addConstr(4 * bobby_hours + 3 * dale_hours + 5 * paul_hours >= 6)
model.addConstr(3 * dale_hours + 5 * paul_hours + 2 * john_hours >= 6)
model.addConstr(4 * bobby_hours + 3 * dale_hours + 5 * paul_hours >= 5)
model.addConstr(3 * dale_hours + 5 * paul_hours + 2 * john_hours >= 5)
model.addConstr(4 * bobby_hours + 3 * dale_hours + 5 * paul_hours + 2 * john_hours >= 5)
model.addConstr(4 * bobby_hours + 3 * dale_hours <= 13)
model.addConstr(4 * bobby_hours + 5 * paul_hours + 2 * john_hours <= 42)
model.addConstr(4 * bobby_hours + 3 * dale_hours + 5 * paul_hours <= 11)


# Productivity rating
model.addConstr(4 * bobby_hours + 2 * dale_hours >= 17)
model.addConstr(2 * dale_hours + 4 * john_hours >= 17)
model.addConstr(4 * bobby_hours + 2 * dale_hours + 4 * paul_hours + 4 * john_hours >= 17)
model.addConstr(4 * bobby_hours + 2 * dale_hours <= 79)

# Computer competence rating
model.addConstr(4 * bobby_hours + 1 * paul_hours >= 6)
model.addConstr(1 * paul_hours + 1 * john_hours >= 9)
model.addConstr(1 * dale_hours + 1 * paul_hours >= 12)
model.addConstr(1 * dale_hours + 1 * john_hours >= 14)
model.addConstr(4 * bobby_hours + 1 * dale_hours >= 5)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * paul_hours >= 8)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * john_hours >= 8)
model.addConstr(1 * dale_hours + 1 * paul_hours + 1 * john_hours >= 8)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * paul_hours >= 11)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * john_hours >= 11)
model.addConstr(1 * dale_hours + 1 * paul_hours + 1 * john_hours >= 11)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * paul_hours >= 16)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * john_hours >= 16)
model.addConstr(1 * dale_hours + 1 * paul_hours + 1 * john_hours >= 16)
model.addConstr(4 * bobby_hours + 1 * dale_hours + 1 * paul_hours + 1 * john_hours >= 16)
model.addConstr(1 * dale_hours + 1 * paul_hours <= 48)
model.addConstr(4 * bobby_hours + 1 * paul_hours <= 28)



# Optimize model
model.optimize()

# Print results
if model.status == GRB.OPTIMAL:
    print('Obj: %g' % model.objVal)
    print('Bobby Hours: %g' % bobby_hours.x)
    print('Dale Hours: %g' % dale_hours.x)
    print('Paul Hours: %g' % paul_hours.x)
    print('John Hours: %g' % john_hours.x)
elif model.status == GRB.INFEASIBLE:
    print('Model is infeasible')
else:
    print('Optimization ended with status %d' % model.status)
```