diff --git a/pydyton/routers/hcbf.py b/pydyton/routers/hcbf.py
index b6280fb1e2407ad9a42f139336b2022351d45006..d6c85c517aa5ed0e241ba4475794f0968e90ea67 100644
--- a/pydyton/routers/hcbf.py
+++ b/pydyton/routers/hcbf.py
@@ -1,74 +1,87 @@
 def hcbf(self, packet, state):
-    if len(self.community) == 0:
-        return False
-
+    if 'hcbf_ui' not in packet.stats:
+        packet.stats = {
+            f'hcbf_{reason}': 0
+            for reason in ['direct', 'ui', 'lp','ui_lonely', 'lp_lonely',
+                           'cbc', 'ncf' ]
+        }
+
+    stats = packet.stats
+    dest = packet.destination
     community = self.network.community
 
-    c_of = lambda n: community[n]
-    same_community = lambda a, b: c_of(a) == c_of(b)
-
-    cbc_of = lambda n, d: community.get_cbc(c_of(n), c_of(d))
-    lp_of = lambda n: community.get_lp(n)
-    ncf_of = lambda n, d: community.get_ncf(n, c_of(d))
-    ui_of = lambda n: community.get_ui(n)
+    def send(to, reason):
+        stats[f'hcbf_{reason}'] += 1
+        self.send(to, packet, reason=reason)
 
-    max = lambda a, b: a if a[0] >= b[0] else b
+    # case 1: direct delivery
+    if dest in self.links:
+        send(dest, 'direct')
+        return True
 
-    if len(c_of(self)) == 0:
-        return False
+    ui = lambda n: community.get_ui(n)
+    lp = lambda n: community.get_lp(n)
+    cbc = lambda n: community.get_cbc(n.community, dest.community)
+    ncf = lambda n: community.get_ncf(n, dest.community)
 
-    dest = packet.destination
-    max_cbc = (cbc_of(self, dest), self)
-    max_lp = (-1, None)
-    max_ncf= (ncf_of(self, dest), self)
-    max_ui = (-1, None)
+    local_community = [
+        met for met in self.links if met in self.community
+    ]
 
-    my_lp = lp_of(self)
-    my_ui = ui_of(self)
+    not_local_community = [
+        met for met in self.links if met not in self.community
+    ]
 
-    for met in self.links:
-        if met == dest:
-            # direct transfer
-            self.send(met, packet)
+    if self.community is dest.community and local_community:
+        max_ui = max(local_community, key=ui)
+        if ui(max_ui) > ui(self):
+            send(max_ui, 'ui')
             return True
+        elif ui(max_ui) < ui(self):
+            return False
+        # ui(max_ui) == ui(self)
 
-        if same_community(met, dest):
-            met_ui = ui_of(met)
-            met_lp = lp_of(met)
-            if met_ui > my_ui:
-                max_ui = max((met_ui, met), max_ui)
-            max_lp = max((met_lp, met), max_lp)
-        elif same_community(met, self):
-            met_cbc = cbc_of(met, dest)
-            max_cbc = max((met_cbc, met), max_cbc)
-        else:
-            met_ncf = ncf_of(met, dest)
-            max_ncf = max((met_ncf, met), max_ncf)
-
-    if max_ui[1] is not None and same_community(max_ui[1], dest):
-        self.send(max_ui[1], packet)
-        return True
-
-    if max_lp[1] is not None and same_community(max_lp[1], dest):
-        self.send(max_lp[1], packet)
-        return True
-
-    if max_cbc[1] is not self:
-        self.send(max_cbc[1], packet)
-        return True
-
-    if max_ncf[1] is not self:
-        self.send(max_ncf[1], packet)
-        return True
+        max_lp = max(local_community, key=lp)
+        if lp(max_lp) > lp(self):
+            send(max_lp, 'lp')
+            return True
+        elif lp(max_lp) < lp(self):
+            return False
+        # lp(max_lp) == lp(self)
+
+    elif not_local_community:
+        max_ncf = max(not_local_community, key=ncf)
+        if ncf(max_ncf) > ncf(self):
+            send(max_ncf, 'ncf')
+            return True
+        elif ncf(max_ncf) < ncf(self):
+            return False
+        # ncf(max_ncf) == ncf(self)
 
-    if max_ui[1] is not None and max_ui[0] > my_ui:
-        self.send(max_ncf[1], packet)
-        self.send(max_ui[1], packet)
-        return True
+        max_cbc = max(not_local_community, key=cbc)
+        if cbc(max_cbc) > cbc(self):
+            send(max_cbc, 'cbc')
+            return True
+        elif cbc(max_cbc) < cbc(self):
+            return False
+        # cbc(max_cbc) == cbc(self)
+
+    elif local_community:
+        max_ui = max(local_community, key=ui)
+        if ui(max_ui) > ui(self):
+            send(max_ui, 'ui_lonely')
+            return True
+        elif ui(max_ui) < ui(self):
+            return False
+        # ui(max_ui) == ui(self)
 
-    if max_lp[1] is not None and max_lp[0] > my_lp:
-        self.send(max_lp[1], packet)
-        return True
+        max_lp = max(local_community, key=lp)
+        if lp(max_lp) > lp(self):
+            send(max_lp, 'lp_lonely')
+            return True
+        elif lp(max_lp) < lp(self):
+            return False
+        # lp(max_lp) == lp(self)
 
     return False