Call Centre Simulation with SimPy: Optimising Customer Service

<p>Call centres live and die by their metrics. Average wait time. Abandonment rate. Service level. Simulation helps you hit your targets without overstaffing.</p> <h2 id="the-call-centre-model">The Call Centre Model</h2> <p>Key components: - <strong>Callers</strong> - Arrive with varying patience - <strong>Agents</strong> - Handle calls - <strong>Queues</strong> - Where callers wait - <strong>Skills</strong> - Some agents handle specific call types - <strong>Abandonment</strong> - Impatient callers hang up</p> <h2 id="basic-call-centre">Basic Call Centre</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="kn">import</span><span class="w"> </span><span class="nn">random</span> <span class="k">class</span><span class="w"> </span><span class="nc">CallCentre</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">num_agents</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">num_agents</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">&#39;calls_handled&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;calls_abandoned&#39;</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;wait_times&#39;</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">&#39;handle_times&#39;</span><span class="p">:</span> <span class="p">[]</span> <span class="p">}</span> <span class="k">def</span><span class="w"> </span><span class="nf">handle_call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">call_id</span><span class="p">,</span> <span class="n">patience</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="c1"># Wait for agent OR give up</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="c1"># Connected to agent</span> <span class="n">wait</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;wait_times&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">wait</span><span class="p">)</span> <span class="c1"># Handle the call</span> <span class="n">handle_time</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">lognormvariate</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">)</span> <span class="c1"># ~7 mins avg</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">handle_time</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;handle_times&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">handle_time</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_handled&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">else</span><span class="p">:</span> <span class="c1"># Caller abandoned</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_abandoned&#39;</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">def</span><span class="w"> </span><span class="nf">call_arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">call_centre</span><span class="p">,</span> <span class="n">arrival_rate</span><span class="p">,</span> <span class="n">mean_patience</span><span class="p">):</span> <span class="n">call_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="n">arrival_rate</span><span class="p">))</span> <span class="n">patience</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="n">mean_patience</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">call_centre</span><span class="o">.</span><span class="n">handle_call</span><span class="p">(</span><span class="n">call_id</span><span class="p">,</span> <span class="n">patience</span><span class="p">))</span> <span class="n">call_id</span> <span class="o">+=</span> <span class="mi">1</span> <span class="c1"># Run simulation</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">cc</span> <span class="o">=</span> <span class="n">CallCentre</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">num_agents</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">call_arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">cc</span><span class="p">,</span> <span class="n">arrival_rate</span><span class="o">=</span><span class="mi">1</span><span class="o">/</span><span class="mf">0.5</span><span class="p">,</span> <span class="n">mean_patience</span><span class="o">=</span><span class="mi">5</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">480</span><span class="p">)</span> <span class="c1"># 8 hours</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Calls handled: </span><span class="si">{</span><span class="n">cc</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_handled&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Calls abandoned: </span><span class="si">{</span><span class="n">cc</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_abandoned&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="n">abandonment_rate</span> <span class="o">=</span> <span class="n">cc</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_abandoned&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="p">(</span><span class="n">cc</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_handled&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="n">cc</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls_abandoned&#39;</span><span class="p">])</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Abandonment rate: </span><span class="si">{</span><span class="n">abandonment_rate</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> </code></pre></div> <h2 id="multi-skill-routing">Multi-Skill Routing</h2> <p>Agents with different skills:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">SkillBasedCallCentre</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">agent_config</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">for</span> <span class="n">skill</span><span class="p">,</span> <span class="n">count</span> <span class="ow">in</span> <span class="n">agent_config</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="p">[</span><span class="n">skill</span><span class="p">]</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">count</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;by_skill&#39;</span><span class="p">:</span> <span class="p">{</span><span class="n">skill</span><span class="p">:</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">skill</span> <span class="ow">in</span> <span class="n">agent_config</span><span class="p">}}</span> <span class="k">def</span><span class="w"> </span><span class="nf">handle_call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">call_id</span><span class="p">,</span> <span class="n">call_type</span><span class="p">,</span> <span class="n">patience</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="c1"># Try primary skill first, then overflow</span> <span class="n">skills_to_try</span> <span class="o">=</span> <span class="p">[</span><span class="n">call_type</span><span class="p">,</span> <span class="s1">&#39;general&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">skill</span> <span class="ow">in</span> <span class="n">skills_to_try</span><span class="p">:</span> <span class="k">if</span> <span class="n">skill</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="p">:</span> <span class="k">continue</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="p">[</span><span class="n">skill</span><span class="p">]</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="n">wait</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="n">handle_time</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">7</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">handle_time</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;by_skill&#39;</span><span class="p">][</span><span class="n">skill</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> <span class="s1">&#39;call_id&#39;</span><span class="p">:</span> <span class="n">call_id</span><span class="p">,</span> <span class="s1">&#39;wait&#39;</span><span class="p">:</span> <span class="n">wait</span><span class="p">,</span> <span class="s1">&#39;handle&#39;</span><span class="p">:</span> <span class="n">handle_time</span> <span class="p">})</span> <span class="k">return</span> <span class="c1"># Call handled</span> <span class="c1"># Update remaining patience</span> <span class="n">patience</span> <span class="o">-=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span><span class="p">)</span> <span class="k">if</span> <span class="n">patience</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span> <span class="k">break</span> <span class="c1"># All options exhausted - abandoned</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Call </span><span class="si">{</span><span class="n">call_id</span><span class="si">}</span><span class="s2"> abandoned&quot;</span><span class="p">)</span> <span class="c1"># Config: 5 sales, 5 support, 3 general (overflow)</span> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;sales&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="s1">&#39;support&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="s1">&#39;general&#39;</span><span class="p">:</span> <span class="mi">3</span><span class="p">}</span> <span class="n">cc</span> <span class="o">=</span> <span class="n">SkillBasedCallCentre</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">config</span><span class="p">)</span> </code></pre></div> <h2 id="vip-priority-queue">VIP Priority Queue</h2> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">PriorityCallCentre</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">num_agents</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">PriorityResource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">num_agents</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;vip&#39;</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">&#39;regular&#39;</span><span class="p">:</span> <span class="p">[]}</span> <span class="k">def</span><span class="w"> </span><span class="nf">handle_call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">call_id</span><span class="p">,</span> <span class="n">is_vip</span><span class="p">,</span> <span class="n">patience</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="n">priority</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">is_vip</span> <span class="k">else</span> <span class="mi">5</span> <span class="n">customer_type</span> <span class="o">=</span> <span class="s1">&#39;vip&#39;</span> <span class="k">if</span> <span class="n">is_vip</span> <span class="k">else</span> <span class="s1">&#39;regular&#39;</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="n">priority</span><span class="o">=</span><span class="n">priority</span><span class="p">)</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="n">wait</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">7</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="n">customer_type</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s1">&#39;wait&#39;</span><span class="p">:</span> <span class="n">wait</span><span class="p">,</span> <span class="s1">&#39;served&#39;</span><span class="p">:</span> <span class="kc">True</span><span class="p">})</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="n">customer_type</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s1">&#39;wait&#39;</span><span class="p">:</span> <span class="n">patience</span><span class="p">,</span> <span class="s1">&#39;served&#39;</span><span class="p">:</span> <span class="kc">False</span><span class="p">})</span> </code></pre></div> <h2 id="time-varying-staffing">Time-Varying Staffing</h2> <p>Match staffing to demand:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">ScheduledCallCentre</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">schedule</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;</span> <span class="sd"> schedule = {</span> <span class="sd"> 0: 5, # Midnight: 5 agents</span> <span class="sd"> 6: 10, # 6am: 10 agents</span> <span class="sd"> 9: 20, # 9am: 20 agents (peak)</span> <span class="sd"> 17: 15, # 5pm: 15 agents</span> <span class="sd"> 21: 8 # 9pm: 8 agents</span> <span class="sd"> }</span> <span class="sd"> &quot;&quot;&quot;</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span> <span class="o">=</span> <span class="n">schedule</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">schedule</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">update_staffing</span><span class="p">())</span> <span class="k">def</span><span class="w"> </span><span class="nf">update_staffing</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">current_hour</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">/</span> <span class="mi">60</span><span class="p">)</span> <span class="o">%</span> <span class="mi">24</span> <span class="c1"># Find applicable staffing level</span> <span class="k">for</span> <span class="n">hour</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="o">.</span><span class="n">keys</span><span class="p">(),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span> <span class="k">if</span> <span class="n">current_hour</span> <span class="o">&gt;=</span> <span class="n">hour</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">_capacity</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">[</span><span class="n">hour</span><span class="p">]</span> <span class="k">break</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">60</span><span class="p">)</span> <span class="c1"># Check hourly</span> </code></pre></div> <h2 id="callback-system">Callback System</h2> <p>Instead of waiting, offer callback:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">CallCentreWithCallback</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">num_agents</span><span class="p">,</span> <span class="n">callback_threshold</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">num_agents</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_threshold</span> <span class="o">=</span> <span class="n">callback_threshold</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_queue</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span><span class="w"> </span><span class="nf">handle_call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">call_id</span><span class="p">,</span> <span class="n">patience</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="c1"># If queue is long, offer callback</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">queue</span><span class="p">)</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_threshold</span><span class="p">:</span> <span class="k">if</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mf">0.7</span><span class="p">:</span> <span class="c1"># 70% accept callback</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_queue</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> <span class="s1">&#39;call_id&#39;</span><span class="p">:</span> <span class="n">call_id</span><span class="p">,</span> <span class="s1">&#39;requested_at&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="p">})</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Call </span><span class="si">{</span><span class="n">call_id</span><span class="si">}</span><span class="s2"> scheduled for callback&quot;</span><span class="p">)</span> <span class="k">return</span> <span class="c1"># Normal queue handling</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">7</span><span class="p">))</span> <span class="k">def</span><span class="w"> </span><span class="nf">process_callbacks</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># Check regularly</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_queue</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">count</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">capacity</span><span class="p">:</span> <span class="n">callback</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback_queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">make_callback</span><span class="p">(</span><span class="n">callback</span><span class="p">))</span> <span class="k">def</span><span class="w"> </span><span class="nf">make_callback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">):</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">request</span><span class="p">()</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="k">yield</span> <span class="n">req</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">7</span><span class="p">))</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Callback to </span><span class="si">{</span><span class="n">callback</span><span class="p">[</span><span class="s1">&#39;call_id&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> completed&quot;</span><span class="p">)</span> </code></pre></div> <h2 id="complete-call-centre-simulation">Complete Call Centre Simulation</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="kn">import</span><span class="w"> </span><span class="nn">random</span> <span class="kn">import</span><span class="w"> </span><span class="nn">numpy</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">np</span> <span class="k">class</span><span class="w"> </span><span class="nc">FullCallCentre</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">config</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">config</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">PriorityResource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;agents&#39;</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">&#39;calls&#39;</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">&#39;service_levels&#39;</span><span class="p">:</span> <span class="p">[],</span> <span class="s1">&#39;queue_lengths&#39;</span><span class="p">:</span> <span class="p">[]</span> <span class="p">}</span> <span class="k">def</span><span class="w"> </span><span class="nf">call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">call_id</span><span class="p">,</span> <span class="n">call_type</span><span class="p">,</span> <span class="n">is_vip</span><span class="p">):</span> <span class="n">arrival</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="n">priority</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">is_vip</span> <span class="k">else</span> <span class="mi">5</span> <span class="n">patience</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;mean_patience&#39;</span><span class="p">])</span> <span class="n">record</span> <span class="o">=</span> <span class="p">{</span> <span class="s1">&#39;call_id&#39;</span><span class="p">:</span> <span class="n">call_id</span><span class="p">,</span> <span class="s1">&#39;type&#39;</span><span class="p">:</span> <span class="n">call_type</span><span class="p">,</span> <span class="s1">&#39;vip&#39;</span><span class="p">:</span> <span class="n">is_vip</span><span class="p">,</span> <span class="s1">&#39;arrival&#39;</span><span class="p">:</span> <span class="n">arrival</span> <span class="p">}</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="n">priority</span><span class="o">=</span><span class="n">priority</span><span class="p">)</span> <span class="k">as</span> <span class="n">req</span><span class="p">:</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">req</span> <span class="o">|</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">patience</span><span class="p">)</span> <span class="k">if</span> <span class="n">req</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;answered&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;wait&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">-</span> <span class="n">arrival</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;answered_in_target&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;wait&#39;</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;target_wait&#39;</span><span class="p">]</span> <span class="c1"># Handle time varies by type</span> <span class="n">handle_times</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;sales&#39;</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span> <span class="s1">&#39;support&#39;</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">&#39;billing&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">}</span> <span class="n">mean_handle</span> <span class="o">=</span> <span class="n">handle_times</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">call_type</span><span class="p">,</span> <span class="mi">7</span><span class="p">)</span> <span class="n">handle</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="n">mean_handle</span><span class="p">)</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">handle</span><span class="p">)</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;handle_time&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">handle</span> <span class="k">else</span><span class="p">:</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;answered&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span> <span class="n">record</span><span class="p">[</span><span class="s1">&#39;wait&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">patience</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">record</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">arrivals</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">call_id</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">call_types</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;sales&#39;</span><span class="p">,</span> <span class="s1">&#39;support&#39;</span><span class="p">,</span> <span class="s1">&#39;billing&#39;</span><span class="p">]</span> <span class="n">type_probs</span> <span class="o">=</span> <span class="p">[</span><span class="mf">0.3</span><span class="p">,</span> <span class="mf">0.5</span><span class="p">,</span> <span class="mf">0.2</span><span class="p">]</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="c1"># Time-varying arrival rate</span> <span class="n">hour</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span> <span class="o">/</span> <span class="mi">60</span><span class="p">)</span> <span class="o">%</span> <span class="mi">24</span> <span class="k">if</span> <span class="mi">9</span> <span class="o">&lt;=</span> <span class="n">hour</span> <span class="o">&lt;=</span> <span class="mi">17</span><span class="p">:</span> <span class="n">rate</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;peak_rate&#39;</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="n">rate</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;off_peak_rate&#39;</span><span class="p">]</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="n">rate</span><span class="p">))</span> <span class="n">call_type</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">choices</span><span class="p">(</span><span class="n">call_types</span><span class="p">,</span> <span class="n">weights</span><span class="o">=</span><span class="n">type_probs</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="n">is_vip</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">random</span><span class="p">()</span> <span class="o">&lt;</span> <span class="mf">0.1</span> <span class="c1"># 10% VIP</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="n">call_id</span><span class="p">,</span> <span class="n">call_type</span><span class="p">,</span> <span class="n">is_vip</span><span class="p">))</span> <span class="n">call_id</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">def</span><span class="w"> </span><span class="nf">monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;queue_lengths&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">({</span> <span class="s1">&#39;time&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="p">,</span> <span class="s1">&#39;queue&#39;</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">queue</span><span class="p">),</span> <span class="s1">&#39;busy&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">agents</span><span class="o">.</span><span class="n">count</span> <span class="p">})</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">duration</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">arrivals</span><span class="p">())</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">monitor</span><span class="p">())</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="n">duration</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">report</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">calls</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stats</span><span class="p">[</span><span class="s1">&#39;calls&#39;</span><span class="p">]</span> <span class="n">answered</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">calls</span> <span class="k">if</span> <span class="n">c</span><span class="p">[</span><span class="s1">&#39;answered&#39;</span><span class="p">]]</span> <span class="n">abandoned</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">calls</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">c</span><span class="p">[</span><span class="s1">&#39;answered&#39;</span><span class="p">]]</span> <span class="nb">print</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">=== Call Centre Report ===&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Total calls: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">calls</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Answered: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">answered</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Abandoned: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">abandoned</span><span class="p">)</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Abandonment rate: </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">abandoned</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">calls</span><span class="p">)</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="k">if</span> <span class="n">answered</span><span class="p">:</span> <span class="n">waits</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span><span class="p">[</span><span class="s1">&#39;wait&#39;</span><span class="p">]</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">answered</span><span class="p">]</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Wait time (answered):&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot; Mean: </span><span class="si">{</span><span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">waits</span><span class="p">)</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> mins&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot; 90th percentile: </span><span class="si">{</span><span class="n">np</span><span class="o">.</span><span class="n">percentile</span><span class="p">(</span><span class="n">waits</span><span class="p">,</span><span class="w"> </span><span class="mi">90</span><span class="p">)</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2"> mins&quot;</span><span class="p">)</span> <span class="n">in_target</span> <span class="o">=</span> <span class="p">[</span><span class="n">c</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">answered</span> <span class="k">if</span> <span class="n">c</span><span class="p">[</span><span class="s1">&#39;answered_in_target&#39;</span><span class="p">]]</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">Service level (target </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s1">&#39;target_wait&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> mins):&quot;</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot; </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">in_target</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">answered</span><span class="p">)</span><span class="si">:</span><span class="s2">.1%</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="c1"># Run</span> <span class="n">random</span><span class="o">.</span><span class="n">seed</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">cc</span> <span class="o">=</span> <span class="n">FullCallCentre</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="p">{</span> <span class="s1">&#39;agents&#39;</span><span class="p">:</span> <span class="mi">15</span><span class="p">,</span> <span class="s1">&#39;peak_rate&#39;</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="c1"># 2 calls/min at peak</span> <span class="s1">&#39;off_peak_rate&#39;</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span> <span class="s1">&#39;mean_patience&#39;</span><span class="p">:</span> <span class="mi">5</span><span class="p">,</span> <span class="c1"># 5 min average patience</span> <span class="s1">&#39;target_wait&#39;</span><span class="p">:</span> <span class="mf">0.5</span> <span class="c1"># 30 second target</span> <span class="p">})</span> <span class="n">cc</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">duration</span><span class="o">=</span><span class="mi">480</span><span class="p">)</span> <span class="c1"># 8 hours</span> <span class="n">cc</span><span class="o">.</span><span class="n">report</span><span class="p">()</span> </code></pre></div> <h2 id="summary">Summary</h2> <p>Call centre simulation captures: - Variable arrival rates and call types - Agent skills and priorities - Customer patience and abandonment - Service level metrics - Staffing optimisation</p> <p>Model the chaos. Meet your SLAs.</p> <h2 id="next-steps">Next Steps</h2> <ul> <li><a href="/blog_posts/simpy-hospital-simulation.html">Hospital Simulation</a></li> <li><a href="/blog_posts/simpy-bank-queue-simulation.html">Bank Queue Simulation</a></li> <li><a href="/blog_posts/simpy-priorityresource-explained.html">PriorityResource Explained</a></li> </ul>

Build Professional Simulations

Break free from commercial software and learn how to build powerful, industry-standard simulations in Python. The Complete Simulation in Python with SimPy Bootcamp gives you everything you need.

Explore the Bootcamp