diff --git a/app/controllers/admin/experiment_projects_controller.rb b/app/controllers/admin/experiment_projects_controller.rb
index f72afffac551b9cfe5d7e49280e1b56413e0b871..53d51ff2f275246a0d6471e4f7c2ec6881aa0df3 100644
--- a/app/controllers/admin/experiment_projects_controller.rb
+++ b/app/controllers/admin/experiment_projects_controller.rb
@@ -27,43 +27,43 @@ module Admin
     end
 
     def create
-      @experiment_project = ExperimentProject.create experiment_project_params
-
-      failed = update_roles(experiment_project_params_with_teachers['teachers'],
-                            :teacher, @experiment_project)
-
-      if @experiment_project.persisted?
-        if failed.empty?
-          flash[:success] = "Successfully created experiment #{@experiment_project.name}"
-        else
-          flash[:danger] = 'Experiment was created, but teachers could not be set'
-        end
-        redirect_to admin_experiment_project_url(@experiment_project)
-      else
-        flash[:danger] = 'Failed to create experiment'
-        render 'new'
-      end
+      @experiment_project = ExperimentProject.create(merge(experiment_project_params))
+      helpers.flash_crud_msg(@experiment_project,
+                             extra_checks: {
+                               'Equality Group' => lambda do
+                                 @experiment_project.equality_group_id ||= @experiment_project.id
+                                 @experiment_project.save
+                                 @experiment_project.persisted?
+                               end,
+                               Role.model_name.human => lambda do
+                                 update_roles(
+                                   experiment_project_params_with_teachers['teachers'], :teacher, @experiment_project
+                                 ).none?
+                               end
+                             },
+                             on_success: proc { redirect_to admin_experiment_project_url(@experiment_project) },
+                             on_part_failure: proc { redirect_to admin_experiment_project_url(@experiment_project) },
+                             on_failure: proc { render 'new' })
     end
 
     def update
-      failed = update_roles(experiment_project_params_with_teachers['teachers'],
-                            :teacher, @experiment_project)
-
-      if @experiment_project.update(experiment_project_params) && failed.empty?
-        flash[:success] = 'Successfully updated the experiment'
-        redirect_to admin_experiment_project_url(@experiment_project)
-      else
-        flash[:danger] = 'Failed to update the experiment'
-        render 'edit'
-      end
+      @experiment_project.update(experiment_project_params)
+      helpers.flash_crud_msg(@experiment_project, html: false,
+                             extra_checks: {
+                               Role.model_name.human => lambda do
+                                 update_roles(
+                                   experiment_project_params_with_teachers['teachers'], :teacher, @experiment_project
+                                 ).none?
+                               end
+                             },
+                             on_success: proc { redirect_to admin_experiment_project_url(@experiment_project) },
+                             on_part_failure: proc { redirect_to admin_experiment_project_url(@experiment_project) },
+                             on_failure: proc { render 'edit' })
     end
 
     def destroy
-      if @experiment_project.destroy
-        flash[:success] = 'Successfully destroyed the experiment'
-      else
-        flash[:danger] = 'Failed to destroy the experiment'
-      end
+      @experiment_project.destroy
+      helpers.flash_crud_msg(@experiment_project)
       redirect_to admin_experiment_projects_url
     end
 
diff --git a/app/models/experiment_project.rb b/app/models/experiment_project.rb
index 015a5c0fec49ca4ca43f51e692922c8d5f4c67df..b4d063cd39ce7ffde63371f07194add7290c58a9 100644
--- a/app/models/experiment_project.rb
+++ b/app/models/experiment_project.rb
@@ -25,27 +25,41 @@ class ExperimentProject < ApplicationRecord
     "Round #{round}: #{name}"
   end
 
-  def advance
-    ExperimentProject.create(attributes.except('id').merge(round: round + 1))
-  end
-
+  # Creates a copy of this project but with the given round set.
+  # @param round_number [Integer] the round number
+  # @return [ExperimentProject]
   def copy_with_round(round_number)
-    ExperimentProject.create(attributes.except('id').merge(round: round_number, original_experiment_project_id: id))
+    ExperimentProject.create(
+      attributes.except('id')
+                .merge(round: round_number,
+                       original_experiment_project_id: id,
+                       equality_group_id: equality_group_id)
+    )
   end
 
-  # Fix me: other projects based on original_id
+  # Gets the projects which are equivalent to this one, which are not in the same round.
+  # This method returns both projects with equal names as well as the projects which were copied from this one.
   def other_same_projects
     ExperimentProject.where(name: name).where.not(round: round)
+                     .or(ExperimentProject.where(equality_group_id: equality_group_id).where.not(round: round).where.not(id: id))
   end
 
+  #
+  # @return [ExperimentProject, Nil] the original project from which this project was copied (if any)
   def original
-    ExperimentProject.where(id: original_experiment_project_id).where.not(id: id)
+    ExperimentProject.where(id: original_experiment_project_id)
+                     .where.not(id: id)
+                     .take
   end
 
+  # Whether this project was copied from another project.
+  # NOTE: If the original was deleted, this method will report false.
+  # @return [Boolean]
   def original?
-    original.empty?
+    original.blank?
   end
 
+  # @return [ActiveRecord::Relation] the users that belong to this project
   def users
     users1.or(users2)
   end
diff --git a/db/migrate/20220621225654_add_equality_group_id_to_experiment_project.rb b/db/migrate/20220621225654_add_equality_group_id_to_experiment_project.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c5f8c03cb6af90a1970d0213d98fa2d735d7a252
--- /dev/null
+++ b/db/migrate/20220621225654_add_equality_group_id_to_experiment_project.rb
@@ -0,0 +1,22 @@
+class AddEqualityGroupIdToExperimentProject < ActiveRecord::Migration[6.1]
+  def change
+    add_column :experiment_projects, :equality_group_id, :int, index: true
+
+    ExperimentProject.where.find_each do |exp|
+      base = exp
+      until base.original_experiment_project_id.nil?
+        nbase = ExperimentProject.find_by(id: base.original_experiment_project_id)
+
+        # Safeguard for copy of no longer existing original
+        break if nbase.nil?
+
+        # Safeguard for cyclic base
+        break if nbase.id == base.id
+
+        base = nbase
+      end
+      # Set equality group id to the id of the base project
+      exp.equality_group_id = base.id
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index fb8d6fa6fe33f2cb52dbbb9c1531ac06f0b31bda..c024fe44e94c99a0c909cc4b5b04fa53f902df47 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2022_06_11_101357) do
+ActiveRecord::Schema.define(version: 2022_06_21_225654) do
 
   create_table "active_storage_attachments", force: :cascade do |t|
     t.string "name", null: false
@@ -298,9 +298,11 @@ ActiveRecord::Schema.define(version: 2022_06_11_101357) do
     t.integer "min_couples", default: 0
     t.boolean "theoretical", default: false
     t.bigint "original_experiment_project_id"
+    t.integer "equality_group_id"
     t.index ["course_edition_id"], name: "index_experiment_projects_on_course_edition_id"
     t.index ["department_id"], name: "index_experiment_projects_on_department_id"
     t.index ["original_experiment_project_id"], name: "index_experiment_projects_on_original_experiment_project_id"
+    t.index ["equality_group_id"], name: "index_experiment_projects_on_equality_group_id"
   end
 
   create_table "faculties", force: :cascade do |t|