diff --git a/src/main/scala/org/scata/algorithm/CBAA.scala b/src/main/scala/org/scata/algorithm/CBAA.scala
new file mode 100644
index 0000000000000000000000000000000000000000..ad01422a30d8b53729cd2246aeff0d04213d687b
--- /dev/null
+++ b/src/main/scala/org/scata/algorithm/CBAA.scala
@@ -0,0 +1,88 @@
+// Copyright (C) Maxime MORGE, 2024
+package org.scata.algorithm
+
+import org.scata.core.{SingleAssignmentProblem, Task, Worker}
+
+/**
+ * The Consensus-Based Auction Algorithm (CBAA) is
+ * a single-assignment strategy
+ */
+class CBAA(pb : SingleAssignmentProblem) {
+
+  var neighbours : Map[Worker, List[Worker]] = fullyConnected()
+
+  var workerTaskList: Map[(Worker, Task), Boolean] = Map[(Worker, Task), Boolean]()
+  var winningBid : Map[(Worker, Task), Int] = Map[(Worker, Task), Int]()
+
+  pb.workers.foreach{ worker=>
+    pb.tasks.foreach{ task =>
+      workerTaskList = workerTaskList.updated((worker, task), false)
+      winningBid = winningBid.updated((worker, task), 0)
+    }
+  }
+
+  /**
+   * Generate a fully connect communication network
+   */
+  private def fullyConnected() :  Map[Worker, List[Worker]] = {
+    var neighbour = Map[Worker, List[Worker]]()
+    pb.workers.foreach{ worker =>
+      neighbour = neighbour.updated(worker, pb.workers.toList)
+    }
+    neighbour
+  }
+
+  /**
+   * Checks if two workers are neighbors
+   * @param worker1 the first worker
+   * @param worker2 the second worker
+   * @return true if they are neighbors, false otherwise
+   */
+  def isNeighbor(worker1: Worker, worker2: Worker): Boolean = neighbours(worker1).contains(worker2)
+
+
+  /**
+   * CBAA Phase 1 for worker i
+   * Selects the best task for the worker based on the cost
+   * @param i index of the worker in the workers set
+   * */
+  def selectTask(i : Int) : Unit = {
+    val worker = pb.workers.toIndexedSeq(i)
+    // Check if the worker has no tasks assigned
+    if (!pb.tasks.exists(task => workerTaskList((worker, task)))) {
+
+      // Determine valid tasks based on cost comparison
+      var validTasks: Map[Task, Boolean] = Map[Task, Boolean]()
+      pb.tasks.foreach { task =>
+        if (pb.cost(worker, task) <= winningBid(worker, task)) {
+          validTasks = validTasks.updated(task, true)
+        } else {
+          validTasks = validTasks.updated(task, false)
+        }
+      }
+      // If there are valid tasks, select the one with the minimum cost
+      if (pb.tasks.exists(task => validTasks(task))) {
+        val bestTask = validTasks.filter(_._2).keys.minBy(task => pb.cost(worker, task))
+        workerTaskList = workerTaskList.updated((worker, bestTask), true)
+        winningBid = winningBid.updated((worker, bestTask), pb.cost(worker, bestTask))
+      }
+    }
+  }
+  /**
+   * TODO CBAA Phase 1 for worker i
+   * @param i index of the worker in the workers set
+   */
+  def consensus(i: Int): Unit = {
+    val worker = pb.workers.toIndexedSeq(i)
+    // Iterate over all tasks
+    pb.tasks.foreach { task =>
+      // Find the minimum winning bid among the neighbors of the worker
+      val minWinningBid = pb.workers
+        .filter(neighbor => isNeighbor(worker, neighbor))
+        .map(neighbor => winningBid((neighbor, task)))
+        .min
+      // Update the winning bid for the worker and task
+      winningBid = winningBid.updated((worker, task), minWinningBid)
+    }
+  }
+}
diff --git a/src/main/scala/org/scata/core/SingleAssignmentProblem.scala b/src/main/scala/org/scata/core/SingleAssignmentProblem.scala
index 939719ca7866db89a9131959e22416e95ce82947..c81de556c1b0d76b1fee6a48add63bfe4f5a3acb 100644
--- a/src/main/scala/org/scata/core/SingleAssignmentProblem.scala
+++ b/src/main/scala/org/scata/core/SingleAssignmentProblem.scala
@@ -12,7 +12,7 @@ import org.scata.utils.RandomUtils
   */
 class SingleAssignmentProblem(val workers: SortedSet[Worker],
                               val tasks : SortedSet[Task],
-                              val cost : Map[(Worker,Task),Double]) {
+                              val cost : Map[(Worker,Task), Int]) {
 
   /**
     * Returns a string describing the MASTAPlus problem
@@ -43,7 +43,7 @@ object SingleAssignmentProblem{
   implicit val order  : Ordering[Double] = Ordering.Double.TotalOrdering
   // eventually Ordering.Double.IeeeOrdering
 
-  private val MAX_COST = 100 // Maximum task cost
+  private val MAX_COST : Int = 100 // Maximum task cost
 
   /**
     * Returns a random single-assignment problem  instance with
@@ -59,7 +59,7 @@ object SingleAssignmentProblem{
     val tasks : SortedSet[Task] = collection.immutable.SortedSet[Task]() ++
       (for (i <- 1 to n) yield new Task(name = "t%02d".format(i)))
 
-    var cost : Map[(Worker,Task),Double] = Map [(Worker,Task),Double]()
+    var cost : Map[(Worker,Task),Int] = Map [(Worker,Task),Int]()
     // Adjust the resource sizes
     workers.foreach{ worker =>
       tasks.foreach{ task =>
diff --git a/src/main/scala/org/scata/core/Worker.scala b/src/main/scala/org/scata/core/Worker.scala
index 931cbb0c4cab6374a78af3cc0c8864a5d852e6f7..d05a470a9f372f46ef7a6ecd6f4213f36c3d31d3 100644
--- a/src/main/scala/org/scata/core/Worker.scala
+++ b/src/main/scala/org/scata/core/Worker.scala
@@ -26,3 +26,4 @@ final class Worker(val name : String) extends Ordered[Worker]{
     -1
   }
 }
+