diff --git a/app/src/main/java/com/yearthreeproject/xbframework/GroupsActivity.java b/app/src/main/java/com/yearthreeproject/xbframework/GroupsActivity.java
index c22c28f9176ca534aec5fb6db4f0a59e1f4ce0a0..909fc4c6d4ca420293ed9ed8dff3c5973552ebdb 100644
--- a/app/src/main/java/com/yearthreeproject/xbframework/GroupsActivity.java
+++ b/app/src/main/java/com/yearthreeproject/xbframework/GroupsActivity.java
@@ -1,19 +1,49 @@
 package com.yearthreeproject.xbframework;
 
+import android.app.AlertDialog;
+import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.widget.Toolbar;
 
+import org.bson.Document;
+
 import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+
+import io.realm.mongodb.App;
+import io.realm.mongodb.mongo.MongoCollection;
+import io.realm.mongodb.mongo.iterable.MongoCursor;
+
+import static com.google.android.gms.tasks.Tasks.await;
 
 public class GroupsActivity extends AppCompatActivity {
+
     private static final String TAG = "GroupsActivity";
+
+    private App realmApp;
+
+    private Menu infoMenu;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
+        realmApp = ((MongoRealmApp)this.getApplication()).getApp();
+
         super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_groups);
+
         Toolbar toolbar = findViewById(R.id.toolbar);
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             toolbar.setNestedScrollingEnabled(false);
@@ -24,7 +54,78 @@ public class GroupsActivity extends AppCompatActivity {
         getSupportActionBar().setDisplayUseLogoEnabled(true);
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
         getSupportActionBar().setDisplayShowHomeEnabled(true);
+        LinearLayout groupLayout = findViewById(R.id.GroupActivityLayout);
 
+        new Thread(()->{
+            try {
+                MongoCollection<Document> groupCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Groups");
+                MongoCursor<Document> found = await(groupCollection.find(new Document("users", new Document("$elemMatch", new Document("$eq", realmApp.currentUser().getId())))).iterator());
+                Log.d(TAG, "onCreate: " + found);
+                while (found.hasNext()) {
+                    Document group = found.next();
+                    Button groupButton = new Button(this);
+                    groupButton.setText(group.getString("name"));
+                    groupButton.setOnClickListener(v ->{
+                        Log.d(TAG, "onCreate: " + group.toString());
+                        Intent groupExperiment = new Intent(this, SurveyResponseActivity.class);
+                        groupExperiment.putExtra("group", group.toJson());
+                        startActivity(groupExperiment);
+                    });
+                    groupLayout.post(() -> groupLayout.addView(groupButton));
+                }
+            } catch(InterruptedException | ExecutionException e){
+                e.printStackTrace();
+            }
+        }).start();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.groups_menu, menu);
+        infoMenu = menu;
+        return true;
+    }
 
+    @Override
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+        int id = item.getItemId();
+        if (id == R.id.add_group)
+        {
+            final String[] m_Text = {""};
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle("Enter the group id:");
+            final EditText input = new EditText(this);
+            input.setInputType(InputType.TYPE_CLASS_TEXT);
+            input.setFilters(new InputFilter[] {new InputFilter.LengthFilter(6)});
+            builder.setView(input);
+            builder.setPositiveButton("OK", (dialog, which) -> {
+                new Thread(() -> {
+                    try {
+                        m_Text[0] = input.getText().toString();
+                        Log.d(TAG, "onOptionsItemSelected: " + m_Text[0]);
+                        // attach the user to the group - if it exists, otherwise tell the user that the group does not exist:
+                        MongoCollection<Document> groupCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Groups");
+                        MongoCollection<Document> userCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Users");
+
+                        // check if the code does not match one that the user is already in then apply the filter
+
+                        Document foundDocument = await(groupCollection.findOneAndUpdate(new Document("identifier", m_Text[0]), new Document("$addToSet", new Document("users", realmApp.currentUser().getId()))));
+                        if(foundDocument != null) {
+                            Log.d(TAG, "onOptionsItemSelected: found document " + foundDocument);
+                            Document userUpdate = await(userCollection.findOneAndUpdate(new Document("_user_id", realmApp.currentUser().getId()), new Document("$addToSet", new Document("groups", foundDocument.getObjectId("_id")))));
+                            Log.d(TAG, "onOptionsItemSelected: updated user" + userUpdate);
+                        } else {
+                            // this means the group does not exist in the database
+                            Log.d(TAG, "onOptionsItemSelected: no document found (do a popup for this result)");
+                        }
+                    } catch (ExecutionException | InterruptedException e) {
+                        e.printStackTrace();
+                    }
+                }).start();
+            });
+            builder.setNegativeButton("Cancel", (dialog, which) -> dialog.cancel());
+            builder.show();
+        }
+        return super.onOptionsItemSelected(item);
     }
-}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/yearthreeproject/xbframework/MainActivity.java b/app/src/main/java/com/yearthreeproject/xbframework/MainActivity.java
index eb8e455123a5f3ae2fb444274fb2fba41dc829ac..58bd88c599d4ca367b8db9ae822eef47a9132c93 100644
--- a/app/src/main/java/com/yearthreeproject/xbframework/MainActivity.java
+++ b/app/src/main/java/com/yearthreeproject/xbframework/MainActivity.java
@@ -52,7 +52,7 @@ public class MainActivity extends AppCompatActivity {
 
     private MongoCollection<Document> userCollection;
     private MongoCollection<Document> experimentsCollection;
-    Menu infoMenu;
+    private Menu infoMenu;
 
     @RequiresApi(api = Build.VERSION_CODES.N)
     @Override
@@ -134,11 +134,9 @@ public class MainActivity extends AppCompatActivity {
 
                                 ProjectMacros.saveFile(MainActivity.this, "localUserData.json", user.toString());
 
-
-                            // DEBUG INTENT FOR QUICK ACCESS TO ANOTHER INTENT
-                            Intent open_quicker_DEBUG = new Intent(this, MetronomeActivity.class);
-                            startActivity(open_quicker_DEBUG);
-
+                                /*// DEBUG INTENT FOR QUICK ACCESS TO ANOTHER INTENT
+                                Intent open_quicker_DEBUG = new Intent(this, MetronomeActivity.class);
+                                startActivity(open_quicker_DEBUG);*/
 
                                 if(user.optJSONObject("current_experiment").optBoolean("locked", false)) checkReleaseFromExperiment();
                                 else checkNotifications();
@@ -156,6 +154,11 @@ public class MainActivity extends AppCompatActivity {
                                     homeLayout.removeView(surveyButton);
                                 }
 
+                                Button metronome = new Button(this);
+                                metronome.setText("Metronome");
+                                homeLayout.addView(metronome);
+                                metronome.setOnClickListener(v -> startActivity(new Intent(this, MetronomeActivity.class)));
+
                                 Button logoutButton = findViewById(R.id.HomeLogoutButton);
                                 logoutButton.setOnClickListener(v -> realmApp.currentUser().logOutAsync(logoutTask -> {
                                     SharedPreferences.Editor savedSettingsEditor = savedSettings.edit();
@@ -171,6 +174,9 @@ public class MainActivity extends AppCompatActivity {
                                 Button progressButton = findViewById(R.id.HomeProgressButton);
                                 progressButton.setOnClickListener(v -> launchProgressPage());
 
+                                Button groupsButton = findViewById(R.id.HomeGroupsButton);
+                                groupsButton.setOnClickListener(v -> startActivity(new Intent(this, GroupsActivity.class)));
+
                                 experimentsButton.setOnClickListener(v -> launchBoxPage());
                                 surveyButton.setOnClickListener(this::surveyButtonEvent);
 
diff --git a/app/src/main/java/com/yearthreeproject/xbframework/SurveyResponseActivity.java b/app/src/main/java/com/yearthreeproject/xbframework/SurveyResponseActivity.java
index 640564569428ca4f33110ca1f1670364847ef671..b48e92a069540ddc18f1b9c03b8583dfc1b3eda3 100644
--- a/app/src/main/java/com/yearthreeproject/xbframework/SurveyResponseActivity.java
+++ b/app/src/main/java/com/yearthreeproject/xbframework/SurveyResponseActivity.java
@@ -9,7 +9,10 @@ import android.text.Html;
 import android.text.InputType;
 import android.text.TextWatcher;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.EditText;
@@ -19,6 +22,7 @@ import android.widget.RelativeLayout;
 import android.widget.TextView;
 import android.widget.Toast;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 import androidx.appcompat.app.AlertDialog;
@@ -28,7 +32,6 @@ import androidx.appcompat.widget.Toolbar;
 import com.google.android.material.floatingactionbutton.FloatingActionButton;
 
 import org.bson.Document;
-import org.bson.types.ObjectId;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -59,6 +62,9 @@ public class SurveyResponseActivity extends AppCompatActivity {
     private final List<JSONObject> surveyResponses = new ArrayList<>();
     private final List<JSONObject> perceptionResponses = new ArrayList<>();
 
+    private JSONObject experimentJSON;
+    private Document groupDocument = null;
+
     @Override
     public boolean onSupportNavigateUp() {
         finish();
@@ -74,24 +80,52 @@ public class SurveyResponseActivity extends AppCompatActivity {
                 .show();
     }
 
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if(getIntent().getStringExtra("group") != null) {
+            getMenuInflater().inflate(R.menu.survey_menu, menu);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
+        int id = item.getItemId();
+        if (id == R.id.menu_group_info)
+        {
+            Log.d(TAG, "onOptionsItemSelected: info pressed");
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
     @SuppressLint("NewApi")
     @RequiresApi(api = Build.VERSION_CODES.KITKAT)
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         realmApp = ((MongoRealmApp)this.getApplication()).getApp();
+
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_survey_response);
 
         Toolbar toolbar = findViewById(R.id.toolbar);
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            toolbar.setNestedScrollingEnabled(false);
-        }
+        toolbar.setNestedScrollingEnabled(false);
         setSupportActionBar(toolbar);
         Objects.requireNonNull(getSupportActionBar()).setDisplayShowHomeEnabled(true);
         getSupportActionBar().setDisplayUseLogoEnabled(true);
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
         getSupportActionBar().setDisplayShowHomeEnabled(true);
 
+        boolean group = getIntent().getStringExtra("group") != null;
+        if(group){
+            groupDocument = Document.parse(getIntent().getStringExtra("group"));
+            setTitle(groupDocument.getString("name"));
+        }
+
+        Log.d(TAG, "onCreate: groupDocument " + groupDocument);
+
+        MongoCollection<Document> experimentCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Experiments");
 
         LinearLayout surveyScrollView = findViewById(R.id.SurveyScrollView);
 
@@ -101,82 +135,114 @@ public class SurveyResponseActivity extends AppCompatActivity {
 
         surveyScrollView.addView(newHR(this, 8, "#888888"));
 
-        try {
-            TextView perceptionTitle = new TextView(this);
-            perceptionTitle.setText("Perception Survey");
-            perceptionTitle.setTextSize(Float.parseFloat("26"));
+        Document finalGroupDocument = groupDocument;
+        new Thread(()->{
+            try {
+                Document experimentDocument = null;
+
+                if(group){
+                    d(TAG, "onCreate: finalGroupDocumentExperiment " + finalGroupDocument.get("current_experiment"));
+                    experimentDocument = await(experimentCollection.findOne(new Document("_id", finalGroupDocument.get("current_experiment", Document.class).getObjectId("id"))));
+                    experimentJSON = new JSONObject(experimentDocument.toJson());
+                } else {
+                    JSONObject localUserJSON = new JSONObject(ProjectMacros.readFile(this, "localUserData.json"));
+                    experimentJSON = localUserJSON.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0);
+                }
 
-            surveyScrollView.addView(perceptionTitle);
+                d(TAG, "onCreate: experimentDocument " + experimentDocument);
 
-            perceptionResponses.add(new JSONObject()
-                    .put("type", "compare")
-                    .put("response", JSONObject.NULL)
-                    .put("question", "How do you feel compared to yesterday?"));
-            surveyScrollView.addView(createNewQuestions("How do you feel compared to yesterday?", "compare", 0, perceptionResponses));
+                TextView perceptionTitle = new TextView(this);
+                perceptionTitle.setText("Perception Survey");
+                perceptionTitle.setTextSize(Float.parseFloat("26"));
 
+                surveyScrollView.post(()->surveyScrollView.addView(perceptionTitle));
 
-            JSONObject localUserJson = new JSONObject(ProjectMacros.readFile(this, "localUserData.json"));
+                perceptionResponses.add(new JSONObject()
+                        .put("type", "compare")
+                        .put("response", JSONObject.NULL)
+                        .put("question", "How do you feel compared to yesterday?"));
+                surveyScrollView.post(()-> surveyScrollView.addView(createNewQuestions("How do you feel compared to yesterday?", "compare", 0, perceptionResponses)));
 
-            if("Sleep".equals(localUserJson.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0).optString("category"))){
-                getSupportActionBar().setLogo(R.mipmap.sleep_logo);
-            } else if ("Eat".equals(localUserJson.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0).optString("category"))){
-                getSupportActionBar().setLogo(R.mipmap.eat_logo);
-            } else if("Engage".equals(localUserJson.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0).optString("category"))){
-                getSupportActionBar().setLogo(R.mipmap.engage_logo);
-            } else {
-                // this is always going to be default since there is no check to see what the result actuall is...
-                getSupportActionBar().setLogo(R.mipmap.ic_launcher);
-            }
+                d(TAG, "onCreate: experimentJSON " + experimentJSON);
 
-            JSONArray completionQuestions = localUserJson.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0).optJSONArray("completion_questions");
+                if("Sleep".equals(experimentJSON.optString("category"))){
+                    getSupportActionBar().setLogo(R.mipmap.sleep_logo);
+                } else if ("Eat".equals(experimentJSON.optString("category"))){
+                    getSupportActionBar().setLogo(R.mipmap.eat_logo);
+                } else if("Engage".equals(experimentJSON.optString("category"))){
+                    getSupportActionBar().setLogo(R.mipmap.engage_logo);
+                } else {
+                    // this is always going to be default since there is no check to see what the result actually is...
+                    toolbar.post(()-> getSupportActionBar().setLogo(R.mipmap.ic_launcher));
+                }
 
+                JSONArray completionQuestions = experimentJSON.optJSONArray("completion_questions");
+                d(TAG, "onCreate: completionQuestions " + completionQuestions);
 
-            if(completionQuestions != null){
-                TextView completionTitle = new TextView(this);
-                completionTitle.setText("Completion Survey");
-                completionTitle.setTextSize(Float.parseFloat("26"));
 
-                surveyScrollView.addView(completionTitle);
+                if(completionQuestions != null){
+                    TextView completionTitle = new TextView(this);
+                    completionTitle.setText("Completion Survey");
+                    completionTitle.setTextSize(Float.parseFloat("26"));
 
-                for (int i = 0; i < completionQuestions.length(); i++) {
-                    completionResponses.add(new JSONObject()
-                            .put("type", completionQuestions.getJSONObject(i).getString("type"))
-                            .put("response", JSONObject.NULL)
-                            .put("question", completionQuestions.getJSONObject(i).getString("question"))
-                            .put("expected", completionQuestions.getJSONObject(i).getString("expected")));
+                    surveyScrollView.post(()-> surveyScrollView.addView(completionTitle));
 
-                    surveyScrollView.addView(createNewQuestions(completionQuestions.getJSONObject(i).optString("question"), completionQuestions.getJSONObject(i).optString("type"), i, completionResponses));
-                }
+                    for (int i = 0; i < completionQuestions.length(); i++) {
+                        completionResponses.add(new JSONObject()
+                                .put("type", completionQuestions.getJSONObject(i).getString("type"))
+                                .put("response", JSONObject.NULL)
+                                .put("question", completionQuestions.getJSONObject(i).getString("question"))
+                                .put("expected", completionQuestions.getJSONObject(i).getString("expected")));
 
-                surveyScrollView.addView(newHR(this, 8, "#888888"));
-            }
+                        int finalI = i;
+                        surveyScrollView.post(()-> {
+                            try {
+                                surveyScrollView.addView(createNewQuestions(completionQuestions.getJSONObject(finalI).optString("question"), completionQuestions.getJSONObject(finalI).optString("type"), finalI, completionResponses));
+                            } catch (JSONException e) {
+                                e.printStackTrace();
+                            }
+                        });
+                    }
+
+                    surveyScrollView.post(()-> surveyScrollView.addView(newHR(this, 8, "#888888")));
+                }
 
-            JSONArray surveyQuestions = localUserJson.getJSONObject("current_experiment").getJSONArray("experiment").getJSONObject(0).optJSONArray("survey_questions");
+                JSONArray surveyQuestions = experimentJSON.optJSONArray("survey_questions");
+                d(TAG, "onCreate: surveyQuestions " + surveyQuestions);
 
-            if(surveyQuestions != null){
-                TextView surveyTagTitle = new TextView(this);
-                surveyTagTitle.setText("Scientific Survey");
-                surveyTagTitle.setTextSize(Float.parseFloat("26"));
+                if(surveyQuestions != null){
+                    TextView surveyTagTitle = new TextView(this);
+                    surveyTagTitle.setText("Scientific Survey");
+                    surveyTagTitle.setTextSize(Float.parseFloat("26"));
 
-                surveyScrollView.addView(surveyTagTitle);
-                for (int i = 0; i < surveyQuestions.length(); i++) {
-                    surveyResponses.add(new JSONObject()
-                            .put("type", surveyQuestions.getJSONObject(i).getString("type"))
-                            .put("agree", surveyQuestions.getJSONObject(i).optString("agree", "good"))
-                            .put("response", JSONObject.NULL)
-                            .put("question", surveyQuestions.getJSONObject(i).getString("question")));
+                    surveyScrollView.post(()-> surveyScrollView.addView(surveyTagTitle));
+                    for (int i = 0; i < surveyQuestions.length(); i++) {
+                        surveyResponses.add(new JSONObject()
+                                .put("type", surveyQuestions.getJSONObject(i).getString("type"))
+                                .put("agree", surveyQuestions.getJSONObject(i).optString("agree", "good"))
+                                .put("response", JSONObject.NULL)
+                                .put("question", surveyQuestions.getJSONObject(i).getString("question")));
 
-                    surveyScrollView.addView(createNewQuestions(surveyQuestions.getJSONObject(i).optString("question"), surveyQuestions.getJSONObject(i).optString("type"), i, surveyResponses));
+                        int finalI = i;
+                        surveyScrollView.post(()-> {
+                            try {
+                                surveyScrollView.addView(createNewQuestions(surveyQuestions.getJSONObject(finalI).optString("question"), surveyQuestions.getJSONObject(finalI).optString("type"), finalI, surveyResponses));
+                            } catch (JSONException e) {
+                                e.printStackTrace();
+                            }
+                        });
+                    }
                 }
+            } catch (JSONException | ExecutionException | InterruptedException e) {
+                e.printStackTrace();
             }
-        } catch (JSONException e) {
-            e.printStackTrace();
-        }
+        }).start();
 
         FloatingActionButton fab = findViewById(R.id.surveyExperimentFAB);
         fab.setOnClickListener(v -> completeSubmission());
     }
 
+    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
     private void completeSubmission() {
         boolean correctSubmission = true;
         ArrayList<Document> rawCompletionResults = new ArrayList<>();
@@ -202,11 +268,11 @@ public class SurveyResponseActivity extends AppCompatActivity {
                             int upperValue = Integer.parseInt(values[1]);
                             if (queryInt <= upperValue &&
                                     lowerValue <= queryInt) {
-                                d("test", "int completed correctly");
+                                d(TAG, "int completed correctly");
                                 completedResults++;
                             }
                         } else if(queryInt == lowerValue) {
-                            d("test", "int completed correctly");
+                            d(TAG, "int completed correctly");
                             completedResults++;
                         }
                     }
@@ -226,17 +292,17 @@ public class SurveyResponseActivity extends AppCompatActivity {
                                     Integer.parseInt(queryTime[1]) <= Integer.parseInt(upperTime[1])){
                                 // If upper hour is the same
                                 // && if the minutes are below the threshold for upper time, if yes, correct
-                                d("test", "date completed correctly");
+                                d(TAG, "date completed correctly");
                                 completedResults++;
                             } else if (Integer.parseInt(lowerTime[0]) == Integer.parseInt(queryTime[0]) &&
                                     Integer.parseInt(lowerTime[1]) <= Integer.parseInt(queryTime[1])){
                                 // If lower hour is the same
                                 // && if the minutes are above the threshold for lowest time, if yes, correct
-                                d("test", "date completed correctly");
+                                d(TAG, "date completed correctly");
                                 completedResults++;
                             } else {
                                 // If neither are the same, and it fits within the range, minutes are irrelevant
-                                d("test", "date completed correctly");
+                                d(TAG, "date completed correctly");
                                 completedResults++;
                             }
                         }
@@ -246,7 +312,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                     if(!completionResponses.get(i).optString("expected").equals("null")){
                         totalPossibleResults++;
                         if(completionResponses.get(i).optString("response").equals(completionResponses.get(i).optString("expected"))) {
-                            d("test", "default completed correctly");
+                            d(TAG, "default completed correctly");
                             completedResults++;
                         }
                     }
@@ -254,9 +320,9 @@ public class SurveyResponseActivity extends AppCompatActivity {
 
         }
 
-        d("test", completedResults + "/" + totalPossibleResults);
+        d(TAG, "completionPercent calculation "+completedResults + "/" + totalPossibleResults);
         double completionPercent = (completedResults / (double) totalPossibleResults)*100;
-        d("test", String.valueOf(completionPercent));
+        d(TAG, "completionPercent " + completionPercent);
 
         int perceptionResponseTotal = 0;
         for (int i = 0; i < surveyResponses.size(); i++) {
@@ -270,7 +336,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
         }
         double responseAverage = (perceptionResponseTotal / (double) (surveyResponses.size()+1))*100;
 
-        d(TAG, "completeSubmission: " + responseAverage);
+        d(TAG, "completeSubmission: responseAverage " + responseAverage);
 
         for(int i = 0; i < perceptionResponses.size(); i++){
             if(perceptionResponses.get(i).optString("response").equals("null")) correctSubmission = false;
@@ -284,89 +350,108 @@ public class SurveyResponseActivity extends AppCompatActivity {
                     .setPositiveButton("Yes", (dialog, which) -> {
                             new Thread(() -> {
                                 try {
+                                    JSONObject localUserJson = new JSONObject(ProjectMacros.readFile(this, "localUserData.json"));
                                     MongoCollection<Document> responseCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Responses");
                                     MongoCollection<Document> completionCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Completions");
                                     MongoCollection<Document> perceptionCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Perceptions");
                                     MongoCollection<Document> userCollection = realmApp.currentUser().getMongoClient("mongodb-atlas").getDatabase("V1").getCollection("Users");
 
-                                    JSONObject userJSON = new JSONObject(ProjectMacros.readFile(this, "localUserData.json"));
-                                    Document currentExperiment = Document.parse(userJSON.getJSONObject("current_experiment").toString());
+                                    Document currentExperiment = Document.parse(experimentJSON.toString());
                                     Date end_date = new Date();
-                                    end_date.setTime(Long.parseLong(userJSON.getJSONObject("current_experiment").getJSONObject("date_until").getString("$date")));
+                                    end_date.setTime(groupDocument.get("current_experiment", Document.class).getDate("date_until").getTime());
 
                                     Document responsesDocument = null;
                                     Document completionsDocument = null;
                                     Document perceptionsDocument = null;
 
                                     if(rawSurveyResults.size() > 0){
+                                        Document queryDocument = new Document("_user_id", realmApp.currentUser().getId());
+                                        queryDocument.append("date", today);
+                                        if(groupDocument != null){
+                                            queryDocument.append("group", groupDocument.getObjectId("_id"));
+                                        } else {
+                                            queryDocument.append("group", new Document("$eq", null));
+                                        }
+
                                         Document responseDocument = new Document("_user_id", realmApp.currentUser().getId())
                                                 .append("date", today)
                                                 .append("end_date", end_date)
                                                 .append("experiment", currentExperiment.getObjectId("id"))
-                                                .append("responses", rawSurveyResults);
+                                                .append("responses", rawSurveyResults)
+                                                .append("group", groupDocument.getObjectId("_id"));
 
-                                        responsesDocument = await(responseCollection.findOneAndUpdate(new Document("_user_id", realmApp.currentUser().getId()).append("date", today),
+                                        responsesDocument = await(responseCollection.findOneAndUpdate(queryDocument,
                                                 responseDocument,
                                                 new FindOneAndModifyOptions().upsert(true)));
-                                        d(TAG, "completeSubmission: " + responsesDocument);
+                                        d(TAG, "completeSubmission: responsesDocument " + responsesDocument);
                                     }
 
                                     if(rawCompletionResults.size() > 0){
+                                        Document queryDocument = new Document("_user_id", realmApp.currentUser().getId());
+                                        queryDocument.append("date", today);
+                                        if(groupDocument != null){
+                                            queryDocument.append("group", groupDocument.getObjectId("_id"));
+                                        } else {
+                                            queryDocument.append("group", new Document("$eq", null));
+                                        }
+
                                         Document completionDocument = new Document("_user_id", realmApp.currentUser().getId())
                                                 .append("date", today)
                                                 .append("end_date", end_date)
                                                 .append("experiment", currentExperiment.getObjectId("id"))
                                                 .append("responses", rawCompletionResults)
-                                                .append("completion_percent", (int) completionPercent);
+                                                .append("completion_percent", (int) completionPercent)
+                                                .append("group", groupDocument.getObjectId("_id"));
 
-                                        completionsDocument = await(completionCollection.findOneAndUpdate(new Document("_user_id", realmApp.currentUser().getId()).append("date", today),
+                                        completionsDocument = await(completionCollection.findOneAndUpdate(queryDocument,
                                                 completionDocument,
                                                 new FindOneAndModifyOptions().upsert(true)));
-                                        d(TAG, "completeSubmission: " + completionsDocument);
+                                        d(TAG, "completeSubmission: completionsDocument " + completionsDocument);
                                     }
 
-                                    d(TAG, "completeSubmission: " + rawPerceptionResults.size());
+                                    d(TAG, "completeSubmission: rawPerceptionResultsSize " + rawPerceptionResults.size());
                                     if(rawPerceptionResults.size() > 0){
+                                        Document queryDocument = new Document("_user_id", realmApp.currentUser().getId());
+                                        queryDocument.append("date", today);
+                                        if(groupDocument != null){
+                                            queryDocument.append("group", groupDocument.getObjectId("_id"));
+                                        } else {
+                                            queryDocument.append("group", new Document("$eq", null));
+                                        }
+
                                         Document perceptionDocument = new Document("_user_id", realmApp.currentUser().getId())
                                                 .append("date", today)
                                                 .append("end_date", end_date)
                                                 .append("experiment", currentExperiment.getObjectId("id"))
-                                                .append("responses", rawPerceptionResults);
+                                                .append("responses", rawPerceptionResults)
+                                                .append("group", groupDocument.getObjectId("_id"));
 
-                                        perceptionsDocument = await(perceptionCollection.findOneAndUpdate(new Document("_user_id", realmApp.currentUser().getId()).append("date", today),
+                                        perceptionsDocument = await(perceptionCollection.findOneAndUpdate(queryDocument,
                                                 perceptionDocument,
                                                 new FindOneAndModifyOptions().upsert(true)));
-                                        d(TAG, "completeSubmission: " + perceptionsDocument);
+                                        d(TAG, "completeSubmission: perceptionsDocument " + perceptionsDocument);
                                     }
 
-                                    Document userDocument = await(userCollection.findOne(new Document("_user_id", realmApp.currentUser().getId())));
-
-                                    ObjectId completionId = null;
-                                    ObjectId responseId = null;
-                                    ObjectId perceptionId = null;
-
-                                    if(completionId != null) completionId = completionsDocument.getObjectId("_id");
-                                    if(responseId != null) responseId = completionsDocument.getObjectId("_id");
-                                    if(perceptionId != null) perceptionId = completionsDocument.getObjectId("_id");
-
-                                    if (completionsDocument != null && !userDocument.getList("experiment_completions", ObjectId.class).contains(completionId))
-                                        userDocument.put("experiment_completions", userDocument.getList("experiment_completions", ObjectId.class).add(completionId));
-
-                                    if (responsesDocument != null && !userDocument.getList("results", ObjectId.class).contains(responseId))
-                                        userDocument.put("results", userDocument.getList("results", ObjectId.class).add(responseId));
-
-                                    if(perceptionsDocument != null && !userDocument.getList("perceptions", ObjectId.class).contains(perceptionId))
-                                        userDocument.put("perceptions", userDocument.getList("perceptions", ObjectId.class).add(perceptionId));
-
-                                    userCollection.updateOne(new Document("_user_id", realmApp.currentUser().getId()),
-                                            userDocument).addOnCompleteListener(user_update_task -> {
-                                        if (user_update_task.isSuccessful()) {
-                                            finish();
-                                        } else {
-                                            d("dbg", String.valueOf(user_update_task.getException()));
-                                        }
-                                    });
+                                    Document userDocument = new Document();
+                                    Document queryDocument = new Document("_user_id", realmApp.currentUser().getId());
 
+                                    if (groupDocument != null) queryDocument.put("group", groupDocument.getObjectId("_id"));
+                                    if (completionsDocument != null) {
+                                        userDocument.put("$addToSet", new Document("experiment_completions", completionsDocument.getObjectId("_id")));
+                                        d(TAG, "completeSubmission: userDocument " + userDocument);
+                                        await(userCollection.updateOne(queryDocument, userDocument));
+                                    }
+                                    if (responsesDocument != null) {
+                                        userDocument.put("$addToSet", new Document("results", responsesDocument.getObjectId("_id")));
+                                        d(TAG, "completeSubmission: userDocument " + userDocument);
+                                        await(userCollection.updateOne(queryDocument, userDocument));
+                                    }
+                                    if (perceptionsDocument != null) {
+                                        userDocument.put("$addToSet", new Document("perceptions", perceptionsDocument.getObjectId("_id")));
+                                        d(TAG, "completeSubmission: userDocument " + userDocument);
+                                        await(userCollection.updateOne(queryDocument, userDocument));
+                                    }
+                                    finish();
                                 } catch (JSONException| InterruptedException | ExecutionException e) {
                                     e.printStackTrace();
                                 }
@@ -484,7 +569,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                                 buttonArray.get(x).setChecked(true);
                                 JSONObject result = responseGroup.get(index)
                                         .put("response", responseString);
-                                d("dbg", String.valueOf(result));
+                                d(TAG, String.valueOf(result));
                                 responseGroup.set(index, result);
                             } catch (JSONException e){
                                 e.printStackTrace();
@@ -541,7 +626,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                                 buttonArray.get(x).setChecked(true);
                                 JSONObject result = responseGroup.get(index)
                                         .put("response", x == 0 ? "Yes" : "No");
-                                d("dbg", String.valueOf(result));
+                                d(TAG, String.valueOf(result));
                                 responseGroup.set(index, result);
                             } catch (JSONException e){
                                 e.printStackTrace();
@@ -568,7 +653,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                     try {
                         JSONObject result = responseGroup.get(index)
                                 .put("response", notificationTextViewTemp);
-                        d("dbg", String.valueOf(result));
+                        d(TAG, String.valueOf(result));
                         responseGroup.set(index, result);
                     } catch (JSONException e){
                         e.printStackTrace();
@@ -601,7 +686,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                     try {
                         JSONObject result = responseGroup.get(index)
                                 .put("response", s.toString());
-                        d("dbg", String.valueOf(result));
+                        d(TAG, String.valueOf(result));
                         responseGroup.set(index, result);
                     } catch (JSONException e){
                         e.printStackTrace();
@@ -630,7 +715,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                     try {
                         JSONObject result = responseGroup.get(index)
                                 .put("response", s.toString());
-                        d("dbg", String.valueOf(result));
+                        d(TAG, String.valueOf(result));
                         responseGroup.set(index, result);
                     } catch (JSONException e){
                         e.printStackTrace();
@@ -728,7 +813,7 @@ public class SurveyResponseActivity extends AppCompatActivity {
                                 buttonArray.get(x).setChecked(true);
                                 JSONObject result = responseGroup.get(index)
                                         .put("response", response);
-                                d("dbg", String.valueOf(result));
+                                d(TAG, String.valueOf(result));
                                 responseGroup.set(index, result);
                             } catch (JSONException e){
                                 e.printStackTrace();
diff --git a/app/src/main/res/layout/activity_groups.xml b/app/src/main/res/layout/activity_groups.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e4abba78bb1b2f3288fe7e833c2199ba5da28453
--- /dev/null
+++ b/app/src/main/res/layout/activity_groups.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".GroupsActivity">
+
+    <com.google.android.material.appbar.AppBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:theme="@style/AppTheme.AppBarOverlay">
+
+        <androidx.appcompat.widget.Toolbar
+            android:id="@+id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@color/colorPrimary"
+            android:minHeight="56dp"
+            android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
+            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
+
+    </com.google.android.material.appbar.AppBarLayout>
+
+
+    <include layout="@layout/content_groups" />
+
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/app/src/main/res/layout/content_groups.xml b/app/src/main/res/layout/content_groups.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8699cbe2752e0370cb5b3215b54a6f2ddf71dd4e
--- /dev/null
+++ b/app/src/main/res/layout/content_groups.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/GroupActivityLayout"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_margin="16dp"
+    android:layout_marginTop="32dp"
+    android:orientation="vertical"
+    app:layout_behavior="@string/appbar_scrolling_view_behavior"
+    tools:context=".GroupsActivity"
+    tools:showIn="@layout/activity_groups">
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index 66db628868dba26f5da5a2b9c01bbd9d301cbd12..3abeef5e21fa88a983288309da336a868f7ac1d9 100644
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -39,6 +39,15 @@
         android:layout_weight="1"
         android:text="@string/MainProgress" />
 
+    <Button
+        android:id="@+id/HomeGroupsButton"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:backgroundTint="@color/colorPrimaryAccent"
+        android:text="@string/MainGroups"
+        android:textColor="@color/colorPrimary" />
+
     <Button
         android:id="@+id/HomeAboutButton"
         android:layout_width="match_parent"
diff --git a/app/src/main/res/menu/groups_menu.xml b/app/src/main/res/menu/groups_menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6ef3c78e5ffd7b9da5d8e022dad9315943c29f7d
--- /dev/null
+++ b/app/src/main/res/menu/groups_menu.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:id="@+id/add_group"
+        android:icon="@android:drawable/ic_menu_add"
+        android:title="Add group"
+        app:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/survey_menu.xml b/app/src/main/res/menu/survey_menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..19b55c4e89b26d781969dcbfe8a64ad2d4e8ef65
--- /dev/null
+++ b/app/src/main/res/menu/survey_menu.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item
+        android:id="@+id/menu_group_info"
+        android:icon="@drawable/ic_baseline_info_24"
+        android:title="GroupSurveyInfo"
+        app:showAsAction="ifRoom" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6c8f16b5ee678ba6509924ef74d8c37e697b5cea..2546347c048e4e96c500ea800e00bd4f482ed8d4 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -180,5 +180,6 @@
     <string name="startButtonLabel">Start</string>
     <string name="stopButtonLabel">Stop</string>
     <string name="two">Two</string>
+    <string name="MainGroups">Groups</string>
     <!-- Metronome strings End -->
 </resources>