## Problem Description and Formulation

The problem is an optimization problem where we need to maximize the objective function:

\[ 7 \times \text{hours worked by Peggy} + 3 \times \text{hours worked by Paul} + 3 \times \text{hours worked by Hank} \]

subject to several constraints related to paperwork competence ratings and productivity ratings.

## Constraints

1. **Paperwork Competence Ratings**:
   - Peggy: 3
   - Paul: 7
   - Hank: 2

2. **Productivity Ratings**:
   - Peggy: 1
   - Paul: 1
   - Hank: 8

3. **Combined Ratings Constraints**:
   - Total combined productivity rating \(\geq 12\)
   - Total combined paperwork competence rating from Peggy and Hank \(\leq 27\)
   - Total combined paperwork competence rating from Paul and Hank \(\leq 27\)
   - Total combined paperwork competence rating from Peggy and Paul \(\leq 34\)
   - Total combined paperwork competence rating from all \(\leq 34\)
   - Total combined productivity rating from Paul and Hank \(\leq 29\)
   - Total combined productivity rating from Peggy and Paul \(\leq 33\)
   - Total combined productivity rating from all \(\leq 33\)

4. **Hours Worked Constraints**:
   - Hours worked by Peggy: integer
   - Hours worked by Paul: can be non-integer
   - Hours worked by Hank: integer

## Gurobi Code Formulation

```python
import gurobi as gp

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

# Define variables
peggy_hours = m.addVar(name="peggy_hours", lowBound=0, vtype=gp.GRB.INTEGER)
paul_hours = m.addVar(name="paul_hours", lowBound=0)
hank_hours = m.addVar(name="hank_hours", lowBound=0, vtype=gp.GRB.INTEGER)

# Objective function
m.setObjective(7 * peggy_hours + 3 * paul_hours + 3 * hank_hours, gp.GRB.MAXIMIZE)

# Constraints
m.addConstr(peggy_hours + paul_hours + hank_hours >= 12, name="productivity_rating_min")
m.addConstr(3 * peggy_hours + 2 * hank_hours <= 27, name="paperwork_peggy_hank")
m.addConstr(7 * paul_hours + 2 * hank_hours <= 27, name="paperwork_paul_hank")
m.addConstr(3 * peggy_hours + 7 * paul_hours <= 34, name="paperwork_peggy_paul")
m.addConstr(3 * peggy_hours + 7 * paul_hours + 2 * hank_hours <= 34, name="paperwork_all")
m.addConstr(paul_hours + 8 * hank_hours <= 29, name="productivity_paul_hank")
m.addConstr(peggy_hours + paul_hours <= 33, name="productivity_peggy_paul")
m.addConstr(peggy_hours + paul_hours + 8 * hank_hours <= 33, name="productivity_all")

# Solve the model
m.optimize()

# Print the solution
if m.status == gp.GRB.OPTIMAL:
    print("Optimal Solution:")
    print(f"Peggy hours: {peggy_hours.varValue}")
    print(f"Paul hours: {paul_hours.varValue}")
    print(f"Hank hours: {hank_hours.varValue}")
    print(f"Objective: {m.objVal}")
else:
    print("No optimal solution found.")
```