_binary From c1ce8c97008feae98bdbafb4b58c2320597c58ef Mon Sep 17 00:00:00 2001
From: Sujith Kakarlapudi <sujith.kakarlapudi@sjsu.edu>
Date: Wed, 12 Feb 2025 12:57:16 -0800
Subject: [PATCH] New Test Data for Impressions in Yioop

---
 src/models/GroupModel.php      |  17 +-
 src/models/ImpressionModel.php |  34 +++-
 tests/ManyUserExperiment.php   | 360 ++++++++-------------------------
 3 files changed, 114 insertions(+), 297 deletions(-)

diff --git a/src/models/GroupModel.php b/src/models/GroupModel.php
index 8d7d0f419..5245287f0 100644
--- a/src/models/GroupModel.php
+++ b/src/models/GroupModel.php
@@ -263,12 +263,14 @@ class GroupModel extends Model implements MediaConstants
      *      live before they expire and are deleted
      * @param int $encryption 0 means don't encrypt group, 1 means encrypt
      *      group
+     * @param boolean $skip_impression false means call intiWithDb, true means
+     *      dont call intiWithDb
      * @return int id of group added
      */
     public function addGroup($group_name, $user_id, $wiki_editors,
         $register = C\REQUEST_JOIN, $member = C\GROUP_READ,
         $voting = C\NON_VOTING_GROUP, $post_lifetime = C\FOREVER,
-        $encryption = 0)
+        $encryption = 0, $skip_impression = false)
     {
         $db = $this->db;
         $private_db = $this->private_db;
@@ -290,10 +292,12 @@ class GroupModel extends Model implements MediaConstants
             JOIN_DATE) VALUES
             ($user_id, $last_id, " . C\ACTIVE_STATUS . ", $now)";
         $db->execute($sql);
-        ImpressionModel::initWithDb($user_id, $last_id, C\GROUP_IMPRESSION,
+        if ($skip_impression == false) {
+            ImpressionModel::initWithDb($user_id, $last_id, C\GROUP_IMPRESSION,
             $db);
-        ImpressionModel::initWithDb(C\PUBLIC_GROUP_ID, $last_id,
+            ImpressionModel::initWithDb(C\PUBLIC_GROUP_ID, $last_id,
             C\GROUP_IMPRESSION, $db);
+        }
         if ($encryption != 0) {
             $sql = "INSERT INTO TYPE_KEYS (TYPE_ID, KEY_NAME) VALUES (?, ?)";
             //AES 256 is 32 bytes long (8*32 bits)
@@ -739,7 +743,8 @@ class GroupModel extends Model implements MediaConstants
                 $where .= " (UG.USER_ID = :user_id) AND ";
             } else {
                 $where .= " (UG.USER_ID = :user_id OR G.REGISTER_TYPE IN (".
-                    C\PUBLIC_BROWSE_REQUEST_JOIN . ",". C\PUBLIC_JOIN .")) AND ";
+                    C\PUBLIC_BROWSE_REQUEST_JOIN . ",". C\PUBLIC_JOIN ."))
+                    AND ";
             }
             $params[":user_id"] = $user_id;
         }
@@ -2983,8 +2988,8 @@ class GroupModel extends Model implements MediaConstants
                         "spreadsheet_data[$i] = $resource_data;" .
                         $spread_config .
                         "\n</script>".
-                        "<div class='wiki-resource-download'><a href='$resource_url' >".
-                            "⤓</a></div>".
+                        "<div class='wiki-resource-download'>
+                        <a href='$resource_url' >"."⤓</a></div>".
                         "<div id='spreadsheet_$i'></div>";
                     $parsed_page = preg_replace('/' .
                         preg_quote($match_string, '/')
diff --git a/src/models/ImpressionModel.php b/src/models/ImpressionModel.php
index 3807e959c..8f41916d6 100644
--- a/src/models/ImpressionModel.php
+++ b/src/models/ImpressionModel.php
@@ -81,7 +81,9 @@ class ImpressionModel extends Model
      */
     public function add($user_id, $item_id, $type_id)
     {
-        $this->addWithDb($user_id, $item_id, $type_id, $this->db);
+        $input_timestamp = time();
+        $this->addWithDb($user_id, $item_id, $type_id, $this->db,
+        $input_timestamp);
     }
     /**
      * Used to add a count record related to a web search to the impression
@@ -113,8 +115,9 @@ class ImpressionModel extends Model
             $this->initWithDb(C\PUBLIC_USER_ID, $db->insertID("QUERY_ITEM"),
                 $impression_type, $db);
         } else {
+            $input_timestamp = time();
             $this->addWithDb(C\PUBLIC_USER_ID, $row['ID'],
-                $impression_type, $db);
+                $impression_type, $db, $input_timestamp);
         }
     }
     /**
@@ -150,8 +153,9 @@ class ImpressionModel extends Model
             $this->initWithDb(C\PUBLIC_USER_ID, $db->insertID("QUERY_ITEM"),
                 C\QUERY_IMPRESSION_EXIT, $db);
         } else {
+            $input_timestamp = time();
             $this->addWithDb(C\PUBLIC_USER_ID, $row['ID'],
-                C\QUERY_IMPRESSION_EXIT, $db);
+                C\QUERY_IMPRESSION_EXIT, $db, $input_timestamp);
         }
     }
     /**
@@ -224,8 +228,10 @@ class ImpressionModel extends Model
     public function mostRecentGroupView($user_id)
     {
         $db = $this->db;
-        $sql = "SELECT COALESCE(MAX(UPDATE_TIMESTAMP), 0) AS MOST_RECENT FROM ".
-            "ITEM_IMPRESSION_SUMMARY WHERE USER_ID = $user_id AND ITEM_TYPE = " .
+        $sql = "SELECT COALESCE(MAX(UPDATE_TIMESTAMP), 0) AS
+            MOST_RECENT FROM ".
+            "ITEM_IMPRESSION_SUMMARY WHERE USER_ID = $user_id AND
+            ITEM_TYPE = " .
             C\GROUP_IMPRESSION . " AND ITEM_ID IN (SELECT GROUP_ID " .
             "FROM USER_GROUP WHERE USER_ID = $user_id AND STATUS = ".
             C\ACTIVE_STATUS . ")  AND UPDATE_PERIOD = ".C\MOST_RECENT_VIEW;
@@ -496,7 +502,8 @@ class ImpressionModel extends Model
         $num_views, $fuzzy_num_views)
     {
             $sql = "UPDATE ITEM_IMPRESSION_STAT SET FUZZY_NUM_VIEWS=?,
-                NUM_VIEWS=? WHERE ITEM_ID=? AND ITEM_TYPE=? AND UPDATE_PERIOD=?";
+                NUM_VIEWS=? WHERE ITEM_ID=? AND ITEM_TYPE=? AND
+                UPDATE_PERIOD=?";
             $parameters = [$fuzzy_num_views, $num_views, $item_id,
                 $item_type, $period];
             $result = $this->db->execute($sql, $parameters);
@@ -557,7 +564,8 @@ class ImpressionModel extends Model
             (?, ?, ?, " . C\FOREVER .", 0, 0, -1, -1)";
         $sql = $db->insertIgnore($sql, $dbinfo);
         $db->execute($sql, [C\PUBLIC_USER_ID, $item_id, $type_id]);
-        self::addWithDb($user_id, $item_id, $type_id, $db);
+        $input_timestamp = time();
+        self::addWithDb($user_id, $item_id, $type_id, $db, $input_timestamp);
     }
     /**
      * Used to add a count record related to a particular user for a particular
@@ -575,20 +583,24 @@ class ImpressionModel extends Model
      * @param object $db a DatasourceManager used to query the Yioop
      *      Yioop database
      */
-    public static function addWithDb($user_id, $item_id, $type_id, $db)
+    public static function addWithDb($user_id, $item_id, $type_id, $db,
+    $input_timestamp)
     {
         if (!C\GROUP_ANALYTICS_MODE || C\GROUP_ANALYTICS_MODE == "0" ||
             !is_numeric($user_id) || !is_numeric($item_id)) {
             return;
         }
+        $current_time = $input_timestamp;
+        $current_time = ($current_time > 0) ? $current_time : time();
         $dbinfo = ["DBMS" => C\DBMS, "DB_HOST" => C\DB_HOST,
             "DB_USER" => C\DB_USER, "DB_PASSWORD" => C\DB_PASSWORD,
             "DB_NAME" => C\DB_NAME];
         $sql = "INSERT INTO ITEM_IMPRESSION VALUES (?, ?, ?, ?)";
         if ($user_id != C\PUBLIC_USER_ID) {
-            $db->execute($sql, [$user_id, $item_id, $type_id, time()]);
+            $db->execute($sql, [$user_id, $item_id, $type_id, $current_time]);
         }
-        $db->execute($sql, [C\PUBLIC_USER_ID, $item_id, $type_id, time()]);
+        $db->execute($sql, [C\PUBLIC_USER_ID, $item_id, $type_id,
+        $current_time]);
         $sql = "DELETE FROM ITEM_IMPRESSION_SUMMARY
             WHERE USER_ID=? AND ITEM_ID=? AND ITEM_TYPE=? AND UPDATE_PERIOD = ".
             C\MOST_RECENT_VIEW;
@@ -596,7 +608,7 @@ class ImpressionModel extends Model
         $sql = "INSERT INTO ITEM_IMPRESSION_SUMMARY VALUES
             (?, ?, ?, " . C\MOST_RECENT_VIEW .", ?, 0, -1, -1)";
         $sql = $db->insertIgnore($sql, $dbinfo);
-        $db->execute($sql, [$user_id, $item_id, $type_id, time()]);
+        $db->execute($sql, [$user_id, $item_id, $type_id, $current_time]);
         $sql = "UPDATE ITEM_IMPRESSION_SUMMARY
             SET NUM_VIEWS = NUM_VIEWS + 1 WHERE USER_ID=? AND
             ITEM_ID=? AND ITEM_TYPE=? AND UPDATE_PERIOD = ". C\FOREVER . "
diff --git a/tests/ManyUserExperiment.php b/tests/ManyUserExperiment.php
index 56a3994cc..6dbf96e80 100644
--- a/tests/ManyUserExperiment.php
+++ b/tests/ManyUserExperiment.php
@@ -36,6 +36,7 @@ namespace seekquarry\yioop\tests;
 use seekquarry\yioop\configs as C;
 use seekquarry\yioop\library as L;
 use seekquarry\yioop\models as M;
+use seekquarry\yioop\models\ImpressionModel;
 
 if (isset($_SERVER['DOCUMENT_ROOT']) && strlen($_SERVER['DOCUMENT_ROOT']) > 0) {
     echo "BAD REQUEST";
@@ -67,6 +68,7 @@ C\nsconddefine("ME_NUM_MIXES", 100);
 C\nsconddefine("ME_NUM_RESOURCES_IMPRESSION", 15);
 $user_model = new M\UserModel();
 $group_model = new M\GroupModel();
+$impression_model = new M\ImpressionModel();
 //Add lots of users
 $user_ids = [];
 for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
@@ -81,7 +83,7 @@ for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
     if ($group_model->getGroupId($personal_group_name) < 0) {
         $group_model->addGroup($personal_group_name,
             $id, ["User$i"], C\INVITE_ONLY_JOIN, C\ACTIVE_STATUS,
-            C\NON_VOTING_GROUP, C\FOREVER, 0);
+            C\NON_VOTING_GROUP, C\FOREVER, 0, true);
     }
     $user_ids[$i] = $id;
 }
@@ -89,13 +91,14 @@ for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
 $group_ids = [];
 for ($i = 0; $i < C\ME_NUM_GROUPS; $i++) {
     echo "Creating Group $i\n";
-    $group_ids[$i] = $group_model->addGroup("Group$i", $user_ids[$i], ["User$i"],
-        C\PUBLIC_JOIN, C\GROUP_READ_WIKI);
+    $group_ids[$i] = $group_model->addGroup("Group$i", $user_ids[$i],["User$i"],
+      C\PUBLIC_JOIN, C\GROUP_READ_WIKI, C\NON_VOTING_GROUP, C\FOREVER,
+    0, true);
 }
 // add lots of users to groups (everyone belongs to at least group 1)
-for ($i = 0; $i < C\ME_NUM_GROUPS; $i++) {
+for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
     $user_id = $user_ids[$i];
-    for ($j = 1; $j < ($i/10) + 1; $j++) {
+    for ($j = 1; $j < ($i/100) + 1; $j++) {
         if ($j != $i) {//by above user $i is owner (and so in) group $i
             echo "Adding User $i (user id $user_id) to ".
                 "Group $j (group id {$group_ids[$j]})\n";
@@ -104,281 +107,78 @@ for ($i = 0; $i < C\ME_NUM_GROUPS; $i++) {
         }
     }
 }
-$impression_model = new M\ImpressionModel();
-// add lots of threads and comments (hence, also impressions) to group 1
-for ($i = 0; $i < C\ME_NUM_THREADS; $i++) {
-    $user_id = $user_ids[$i];
-    $title = "My first thread: User $user_id";
-    echo "Adding User $user_id  Group {$group_ids[1]} Thread\n";
-    $parent_id = $group_model->addGroupItem(0, $group_ids[1], $user_id,
-        $title, "I really like this thread, User:$user_id");
-    $title = "--" . $title;
-    for ($j = 0; $j < ($i / 10) + 1; $j++) {
-        $comment_user_id = $user_ids[$j];
-        $impression_model->add($comment_user_id, $parent_id,
-            C\THREAD_IMPRESSION);
-        $impression_model->add($comment_user_id, $group_ids[1],
-            C\GROUP_IMPRESSION);
-        $group_model->addGroupItem($parent_id, $group_ids[1], $comment_user_id,
-            $title, "I totally agree with you, User:$comment_user_id");
-    }
-}
-// add lots of roles
-$role_model = new M\RoleModel();
-$user_id = $user_ids[2];
-for ($i = 0; $i < C\ME_NUM_ROLES; $i++) {
-    echo "Creating Role $i\n";
-    $role_model->addRole("Role$i");
-    $role_id =  $role_model->getRoleId("Role$i");
-    $role_model->addUserRole($user_id, $role_id);
-}
-$crawl_model = new M\CrawlModel();
-$mix = [];
-$mix['TIMESTAMP'] = time();
-$mix['FRAGMENTS'] = [];
-$mix['OWNER_ID'] = C\ROOT_ID;
-$mix['PARENT'] = -1;
-for ($i = 0; $i < C\ME_NUM_MIXES; $i++) {
-    echo "Creating Crawl Mix $i\n";
-    $mix['TIMESTAMP']++;
-    $mix['NAME'] = "Mix$i";
-    $crawl_model->setCrawlMix($mix);
-}
-// add wiki page to group 1
-$page = <<< 'EOD'
-page_type=media_list
-
-page_alias=
-
-page_border=solid-border
-
-toc=true
-
-title=
-
-author=
-
-robots=
+class ManyUserExperiment extends ImpressionModel
+{
+    /**
+    * Fetches and processes user-group relationships, and associates groups
+    * with pages in the system.
+    *
+    * This function performs the following tasks:
+    * 1. Retrieves unique USER_IDs and GROUP_IDs from the USER_GROUP table,
+    * excluding specific USER_IDs and GROUP_IDs.
+    * 2. Collects a list of unique GROUP_IDs and USER_IDs.
+    * 3. Fetches PAGE_IDs associated with the unique GROUP_IDs
+    * from the GROUP_PAGE table.
+    * 4. Generates random timestamps within the past year.
+    * 5. For each unique USER_ID, associates them with each PAGE_ID
+    * by calling the `addWithDb` function, passing the appropriate parameters
+    * including a random timestamp.
+    * 6. Logs the additions to the database for debugging and tracking purposes.
+    *
+    * This function is designed to populate the system with test data by
+    * associating users with group pages, creating impressions.
+    *
+    */
 
-description=
-
-alternative_path=
-
-page_header=
-
-page_footer=
-
-sort=aname
-
-update_description=files-and-folders
-
-END_HEAD_VARS
-==This is test page.==
-EOD;
-$page_content = str_replace("'", "&#039;", $page);
-$page_name = "Test";
-echo "Adding wiki page $page_name to group $group_ids[0]...\n";
-$page_id = $group_model->setPageName($user_ids[0], $group_ids[0], $page_name,
-    $page_content, "en-US", "Creating test wiki page",
-    "{$page_name} Wiki Page Created!", "Discuss the page in this thread!");
-echo "Added the wiki page...\n";
-echo "Creating movies folder and adding dummy mp4 resources\n";
-$resources = [];
-$folders_path = [];
-// create movie folder in the wiki page
-$folders = $group_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
-    "movies", true);
-// add resources to the movies subfolder
-$movies = [
-    "The 355.mp4",
-    "The Legend of La Llorona.mp4",
-    "The Commando.mp4",
-    "American Siege.mp4",
-    "Scream.mp4",
-    "Hotel Transylvania Transformania.mp4",
-    "Shattered.mp4",
-    "The Royal Treatment.mp4",
-    "Redeeming Love.mp4",
-    "The Kings Daughter.mp4",
-    "The Tiger Rising.mp4",
-    "Hellblazers.mp4",
-    "The Fallout.mp4",
-    "Home Team.mp4",
-    "The Ice Age Adventures of Buck Wild.mp4",
-    "Clean.mp4",
-    "Sundown.mp4",
-    "Jackass Forever.mp4",
-    "Moonfall.mp4",
-    "Last Looks.mp4",
-    "The Long Night.mp4",
-    "Kimi.mp4",
-    "Shut In.mp4",
-    "Death on the Nile.mp4",
-    "Marry Me.mp4",
-    "Blacklight.mp4",
-    "I Want You Back.mp4",
-    "Tall Girl 2.mp4",
-    "The Sky Is Everywhere.mp4",
-    "The In Between.mp4",
-    "Fistful of Vengeance.mp4",
-    "Uncharted.mp4",
-    "Dog.mp4",
-    "Texas Chainsaw Massacre.mp4",
-    "The Cursed.mp4",
-    "A Fairy Tale After All.mp4",
-    "Cyrano.mp4",
-    "Studio 666.mp4",
-    "A Madea Homecoming.mp4",
-    "No Exit.mp4",
-    "Gasoline Alley.mp4",
-    "The Batman.mp4",
-    "After Yang.mp4",
-    "Fresh.mp4",
-    "A Day to Die.mp4",
-    "The Adam Project.mp4",
-    "Turning Red.mp4",
-    "Tysons Run.mp4",
-    "Rescued by Ruby.mp4",
-    "The Outfit.mp4",
-    "Deep Water.mp4",
-    "Cheaper by the Dozen.mp4",
-    "Windfall.mp4",
-    "X.mp4",
-    "Umma.mp4",
-    "Alice.mp4",
-    "Master.mp4",
-    "Measure of Revenge.mp4",
-    "The Lost City.mp4",
-    "Everything Everywhere All at Once.mp4"
-];
-$resources[] = $movies;
-$folders_path[] = $folders;
-foreach ($movies as $movie) {
-    $group_model->setPageResource($movie, "This is test data", $group_ids[0],
-        $page_id, "movies");
-}
-echo "Creating web_series folder and adding dummy mp4 resources\n";
-// create web_series folder in the wiki page
-$folders = $group_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
-    "web_series", true);
-// add resources to the web_series subfolder
-$web_series = [
-    "Unforgotten Season 2.mp4",
-    "The Devils Hour Season 1.mp4",
-    "Indian Predator Murder in a Courtroom.mp4",
-    "If Only.mp4",
-    "Flames Season 3.mp4",
-    "Jhansi.mp4",
-    "Dubai Bling.mp4",
-    "The Mysterious Benedict Society Season 2.mp4",
-    "Sumo Do, Sumo Dont!.mp4",
-    "Star Wars Tales of the Jedi.mp4",
-    "Shadow Detective.mp4",
-    "Tripling Season 3.mp4",
-    "The Serpent Queen.mp4",
-    "The Peripheral.mp4",
-    "From Scratch.mp4",
-    "Four More Shots Please! Season 3.mp4",
-    "Barbarians Season 2.mp4",
-    "Notre-Dame.mp4",
-    "Shantaram.mp4",
-    "Mismatched Season 2.mp4",
-    "Good Bad Girl.mp4",
-    "Everything Calls for Salvation.mp4",
-    "The Watcher.mp4",
-    "The Playlist.mp4",
-    "Exception Season 1.mp4",
-    "Rookie Cops.mp4",
-    "Big Shot Season 2.mp4",
-    "Belascoarán, Pl Season 1.mp4",
-    "Werewolf by Night.mp4",
-    "The Midnight Club.mp4",
-    "Man on Pause.mp4",
-    "Derry Girls Season 3.mp4",
-    "Conversations with a Killer The Jeffrey Dahmer Tapes.mp4",
-    "Aashiqana Season 2.mp4",
-    "Shipwreck Hunters Australia.mp4"
-];
-$resources[] = $web_series;
-$folders_path[] = $folders;
-foreach ($web_series as $series) {
-    $group_model->setPageResource($series, "This is test data", $group_ids[0],
-        $page_id, "web_series");
-}
-echo "Creating books folder and adding dummy pdf resources\n";
-// create books folder in the wiki page
-$folders = $group_model->getGroupPageResourcesFolders($group_ids[0], $page_id,
-    "books", true);
-// add resources to the books subfolder
-$books = [
-    "Book Lovers.pdf",
-    "Gallant.pdf",
-    "Daughter of the Moon Goddess.pdf",
-    "Book of Night.pdf",
-    "The Girl Who Fell Beneath the Sea.pdf",
-    "I Kissed Shara Wheeler.pdf",
-    "House of Sky and Breath.pdf",
-    "A Magic Steeped in Poison.pdf",
-    "Love on the Brain.pdf",
-    "Only a Monster.pdf",
-    "This Woven Kingdom.pdf",
-    "Delilah Green Doesnt Care.pdf",
-    "Portrait of a Thief.pdf",
-    "The Paris Apartment.pdf",
-    "Foul Lady Fortune.pdf",
-    "Bloodmarked.pdf",
-    "Belladonna.pdf",
-    "Ophelia After All.pdf",
-    "Violet Made of Thorns.pdf",
-    "Carrie Soto Is Back.pdf",
-    "Hook, Line, and Sinker.pdf",
-    "The MaidThe Maid.pdf",
-    "A Far Wilder Magic.pdf",
-    "Sea of Tranquility.pdf",
-    "The Book of Cold Cases.pdf",
-    "All My Rage.pdf",
-    "Kaikeyi.pdf",
-    "How High We Go in the Dark.pdf",
-    "The Sunbearer Trials.pdf",
-    "Hotel Magnifique.pdf",
-    "What Moves the Dead.pdf",
-    "Stuck with You.pdf",
-    "Below Zero.pdf",
-    "The House Across the Lake.pdf",
-    "Nettle & Bone.pdf",
-    "A Million to One.pdf",
-    "An Arrow to the Moon.pdf",
-    "Something Wilder.pdf",
-    "Anatomy: A Love Story.pdf",
-    "The Final Gambit.pdf",
-    "The City of Dusk.pdf",
-    "The Ivory Key.pdf",
-    "So This Is Ever After.pdf",
-    "The Book Eaters.pdf",
-    "The Red Palace.pdf",
-    "The Stardust Thief.pdf",
-    "She Gets the Girl.pdf",
-    "Weather Girl.pdf",
-    "The Bone Spindle.pdf"
-];
-$resources[] = $books;
-$folders_path[] = $folders;
-foreach ($books as $book) {
-    $group_model->setPageResource($book, "This is test data", $group_ids[0],
-        $page_id, "books");
-}
-echo "Creating users impression with random resources\n";
-for ($i = 0; $i < C\ME_NUM_USERS; $i++) {
-    $user_id = $user_ids[$i];
-    for ($j = 0; $j < C\ME_NUM_RESOURCES_IMPRESSION; $j++) {
-        $resource_type = rand(0,2);
-        $resource_index = rand(0, count($resources[$resource_type]) - 1);
-        $resource_name = $resources[$resource_type][$resource_index];
-        echo "Creating RESOURCE_IMPRESSION for user $user_id with resource" .
-            " $resource_name\n";
-        $resource_id = unpack('n', md5($group_ids[0] . $page_id .
-            $folders_path[$resource_type][1] . "/" . $resource_name, true))[1];
-        $impression_model->add($user_id, $resource_id,
-            C\RESOURCE_IMPRESSION);
+    public function addTestData()
+    {
+        $db = $this->db;
+        $user_group_list = [];
+        $group_id_list = [];
+        $unique_user_id_list = [];
+        /*
+           Here we exclude the root user ID and public user ID
+           while adding the test data
+         */
+        $sql_user_group_query = "SELECT USER_ID, GROUP_ID FROM USER_GROUP WHERE
+        USER_ID NOT IN (1, 2) AND GROUP_ID != 2";
+        $result_user_group_query = $db->execute($sql_user_group_query);
+        while ($row = $db->fetchArray($result_user_group_query)) {
+            $user_group_list[] = ['user_id' => $row['USER_ID'],
+            'group_id' => $row['GROUP_ID']];
+            $group_id_list[] = $row['GROUP_ID'];
+            $unique_user_id_list[] = $row['USER_ID'];
+        }
+        $unique_user_id_list = array_unique($unique_user_id_list);
+        $unique_group_id_list = array_unique($group_id_list);
+        $page_id_list = [];
+        if (!empty($unique_group_id_list)) {
+            $chunked_group_id_list = array_chunk($unique_group_id_list, 100);
+            foreach ($chunked_group_id_list as $chunk) {
+                $placeholders = implode(',', array_fill(0, count($chunk), '?'));
+                $sql_group_page_query = "SELECT ID FROM GROUP_PAGE
+                WHERE GROUP_ID IN ($placeholders)";
+                $result_group_page_query = $db->execute($sql_group_page_query,
+                $chunk);
+                while ($row = $db->fetchArray($result_group_page_query)) {
+                    $page_id_list[] = $row['ID'];
+                }
+            }
+        }
+        $current_timestamp = time();
+        $one_year_ago_timestamp = $current_timestamp - (365 * 24 * 60 * 60);
+        foreach ($unique_user_id_list as $user_id) {
+            foreach ($page_id_list as $page_id) {
+                $random_timestamp = rand($one_year_ago_timestamp,
+                $current_timestamp - 60);
+                $this->addWithDb($user_id, $page_id, C\WIKI_IMPRESSION,
+                $db, $random_timestamp);
+                L\crawlLog("Adding to DB with USER_ID: $user_id,
+                PAGE_ID: $page_id, TIMESTAMP: $random_timestamp");
+            }
+        }
     }
 }
+
+$experiment = new ManyUserExperiment();
+$experiment->addTestData();
-- 
2.46.0.windows.1

