createsim.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #!/usr/bin/env php
  2. <?php
  3. /*
  4. * StatusNet - the distributed open-source microblogging tool
  5. * Copyright (C) 2008, 2009, StatusNet, Inc.
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. define('INSTALLDIR', realpath(dirname(__FILE__) . '/..'));
  21. $shortoptions = 'b:g:j:n:t:u:w:x:z:';
  22. $longoptions = array(
  23. 'subscriptions=',
  24. 'groups=',
  25. 'joins=',
  26. 'notices=',
  27. 'tags=',
  28. 'users=',
  29. 'words=',
  30. 'prefix=',
  31. 'groupprefix=',
  32. // 'faves=',
  33. );
  34. $helptext = <<<END_OF_CREATESIM_HELP
  35. Creates a lot of test users and notices to (loosely) simulate a real server.
  36. -b --subscriptions Average subscriptions per user (default no. users/20)
  37. -g --groups Number of groups (default 20)
  38. -j --joins Number of groups per user (default 5)
  39. -n --notices Average notices per user (default 100)
  40. -t --tags Number of distinct hash tags (default 10000)
  41. -u --users Number of users (default 100)
  42. -w --words Words file (default '/usr/share/dict/words')
  43. -x --prefix User name prefix (default 'testuser')
  44. -z --groupprefix Group name prefix (default 'testgroup')
  45. END_OF_CREATESIM_HELP;
  46. require_once INSTALLDIR.'/scripts/commandline.inc';
  47. // XXX: make these command-line options
  48. function newUser($i)
  49. {
  50. global $userprefix;
  51. $user = User::register(array('nickname' => sprintf('%s%d', $userprefix, $i),
  52. 'password' => sprintf('password%d', $i),
  53. 'fullname' => sprintf('Test User %d', $i)));
  54. if (!empty($user)) {
  55. $user->free();
  56. }
  57. }
  58. function newGroup($i, $j)
  59. {
  60. global $groupprefix;
  61. global $userprefix;
  62. // Pick a random user to be the admin
  63. $n = rand(0, max($j - 1, 0));
  64. $user = User::getKV('nickname', sprintf('%s%d', $userprefix, $n));
  65. $group = User_group::register(array('nickname' => sprintf('%s%d', $groupprefix, $i),
  66. 'local' => true,
  67. 'userid' => $user->id,
  68. 'fullname' => sprintf('Test Group %d', $i)));
  69. }
  70. function newNotice($i, $tagmax)
  71. {
  72. global $userprefix;
  73. $options = array('scope' => Notice::defaultScope());
  74. $n = rand(0, $i - 1);
  75. $user = User::getKV('nickname', sprintf('%s%d', $userprefix, $n));
  76. $is_reply = rand(0, 1);
  77. $content = testNoticeContent();
  78. if ($is_reply == 0) {
  79. $stream = new InboxNoticeStream($user->getProfile(), $user->getProfile());
  80. $notices = $stream->getNotices(0, 20);
  81. if ($notices->N > 0) {
  82. $nval = rand(0, $notices->N - 1);
  83. $notices->fetch(); // go to 0th
  84. for ($i = 0; $i < $nval; $i++) {
  85. $notices->fetch();
  86. }
  87. $options['reply_to'] = $notices->id;
  88. $dont_use_nickname = rand(0, 2);
  89. if ($dont_use_nickname != 0) {
  90. $rprofile = $notices->getProfile();
  91. $content = "@".$rprofile->nickname." ".$content;
  92. }
  93. $private_to_addressees = rand(0, 4);
  94. if ($private_to_addressees == 0) {
  95. $options['scope'] |= Notice::ADDRESSEE_SCOPE;
  96. }
  97. }
  98. } else {
  99. $is_directed = rand(0, 4);
  100. if ($is_directed == 0) {
  101. $subs = $user->getSubscribed(0, 100)->fetchAll();
  102. if (count($subs) > 0) {
  103. $seen = array();
  104. $f = rand(0, 9);
  105. if ($f <= 6) {
  106. $addrs = 1;
  107. } else if ($f <= 8) {
  108. $addrs = 2;
  109. } else {
  110. $addrs = 3;
  111. }
  112. for ($m = 0; $m < $addrs; $m++) {
  113. $x = rand(0, count($subs) - 1);
  114. if ($seen[$x]) {
  115. continue;
  116. }
  117. if ($subs[$x]->id == $user->id) {
  118. continue;
  119. }
  120. $seen[$x] = true;
  121. $rprofile = $subs[$x];
  122. $content = "@".$rprofile->nickname." ".$content;
  123. }
  124. $private_to_addressees = rand(0, 4);
  125. if ($private_to_addressees == 0) {
  126. $options['scope'] |= Notice::ADDRESSEE_SCOPE;
  127. }
  128. }
  129. }
  130. }
  131. $has_hash = rand(0, 2);
  132. if ($has_hash == 0) {
  133. $hashcount = rand(0, 2);
  134. for ($j = 0; $j < $hashcount; $j++) {
  135. $h = rand(0, $tagmax);
  136. $content .= " #tag{$h}";
  137. }
  138. }
  139. $in_group = rand(0, 5);
  140. if ($in_group == 0) {
  141. $groups = $user->getGroups();
  142. if ($groups instanceof User_group) {
  143. $gval = rand(0, $groups->N - 1);
  144. $groups->fetch(); // go to 0th
  145. for ($i = 0; $i < $gval; $i++) {
  146. $groups->fetch();
  147. }
  148. $options['groups'] = array($groups->id);
  149. $content = "!".$groups->nickname." ".$content;
  150. $private_to_group = rand(0, 2);
  151. if ($private_to_group == 0) {
  152. $options['scope'] |= Notice::GROUP_SCOPE;
  153. }
  154. }
  155. }
  156. $private_to_site = rand(0, 4);
  157. if ($private_to_site == 0) {
  158. $options['scope'] |= Notice::SITE_SCOPE;
  159. }
  160. $notice = Notice::saveNew($user->id, $content, 'createsim', $options);
  161. }
  162. /* Plugins should be part of the simulation too!
  163. function newMessage($i)
  164. {
  165. global $userprefix;
  166. $n = rand(0, $i - 1);
  167. $user = User::getKV('nickname', sprintf('%s%d', $userprefix, $n));
  168. $content = testNoticeContent();
  169. $friends = $user->mutuallySubscribedUsers()->fetchAll();
  170. if (count($friends) == 0) {
  171. return;
  172. }
  173. $j = rand(0, count($friends) - 1);
  174. $other = $friends[$j];
  175. $message = Message::saveNew($user->id, $other->id, $content, 'createsim');
  176. }*/
  177. function newSub($i)
  178. {
  179. global $userprefix;
  180. $f = rand(0, $i - 1);
  181. $fromnick = sprintf('%s%d', $userprefix, $f);
  182. $from = User::getKV('nickname', $fromnick);
  183. if (empty($from)) {
  184. throw new Exception("Can't find user '$fromnick'.");
  185. }
  186. $t = rand(0, $i - 1);
  187. if ($t == $f) {
  188. $t++;
  189. if ($t > $i - 1) {
  190. $t = 0;
  191. }
  192. }
  193. $tunic = sprintf('%s%d', $userprefix, $t);
  194. $to = User::getKV('nickname', $tunic);
  195. if (!($to instanceof User)) {
  196. throw new Exception("Can't find user '$tunic'.");
  197. }
  198. Subscription::start($from->getProfile(), $to->getProfile());
  199. $from->free();
  200. $to->free();
  201. }
  202. function newJoin($u, $g)
  203. {
  204. global $userprefix;
  205. global $groupprefix;
  206. $userNumber = rand(0, $u - 1);
  207. $userNick = sprintf('%s%d', $userprefix, $userNumber);
  208. $user = User::getKV('nickname', $userNick);
  209. if (empty($user)) {
  210. throw new Exception("Can't find user '$fromnick'.");
  211. }
  212. $groupNumber = rand(0, $g - 1);
  213. $groupNick = sprintf('%s%d', $groupprefix, $groupNumber);
  214. $group = User_group::getKV('nickname', $groupNick);
  215. if (empty($group)) {
  216. throw new Exception("Can't find group '$groupNick'.");
  217. }
  218. if (!$user->isMember($group)) {
  219. $user->joinGroup($group);
  220. }
  221. }
  222. /* Plugins should be part of the simulation too!
  223. function newFave($u)
  224. {
  225. global $userprefix;
  226. global $groupprefix;
  227. $userNumber = rand(0, $u - 1);
  228. $userNick = sprintf('%s%d', $userprefix, $userNumber);
  229. $user = User::getKV('nickname', $userNick);
  230. if (empty($user)) {
  231. throw new Exception("Can't find user '$userNick'.");
  232. }
  233. // NB: it's OK to like your own stuff!
  234. $otherNumber = rand(0, $u - 1);
  235. $otherNick = sprintf('%s%d', $userprefix, $otherNumber);
  236. $other = User::getKV('nickname', $otherNick);
  237. if (empty($other)) {
  238. throw new Exception("Can't find user '$otherNick'.");
  239. }
  240. $notices = $other->getNotices()->fetchAll();
  241. if (count($notices) == 0) {
  242. return;
  243. }
  244. $idx = rand(0, count($notices) - 1);
  245. $notice = $notices[$idx];
  246. if ($user->hasFave($notice)) {
  247. return;
  248. }
  249. Fave::addNew($user->getProfile(), $notice);
  250. }*/
  251. function testNoticeContent()
  252. {
  253. global $words;
  254. if (is_null($words)) {
  255. return "test notice content";
  256. }
  257. $cnt = rand(3, 8);
  258. $ids = array_rand($words, $cnt);
  259. foreach ($ids as $id) {
  260. $parts[] = $words[$id];
  261. }
  262. $text = implode(' ', $parts);
  263. if (mb_strlen($text) > 80) {
  264. $text = substr($text, 0, 77) . "...";
  265. }
  266. return $text;
  267. }
  268. //function main($usercount, $groupcount, $noticeavg, $subsavg, $joinsavg, $favesavg, $messageavg, $tagmax)
  269. function main($usercount, $groupcount, $noticeavg, $subsavg, $joinsavg, $tagmax)
  270. {
  271. global $config;
  272. $config['site']['dupelimit'] = -1;
  273. $n = 0;
  274. $g = 0;
  275. // Make users first
  276. $preuser = min($usercount, 5);
  277. for ($j = 0; $j < $preuser; $j++) {
  278. printfv("$i Creating user $n\n");
  279. newUser($n);
  280. $n++;
  281. }
  282. $pregroup = min($groupcount, 3);
  283. for ($k = 0; $k < $pregroup; $k++) {
  284. printfv("$i Creating group $g\n");
  285. newGroup($g, $n);
  286. $g++;
  287. }
  288. // # registrations + # notices + # subs
  289. //$events = $usercount + $groupcount + ($usercount * ($noticeavg + $subsavg + $joinsavg + $favesavg + $messageavg));
  290. $events = $usercount + $groupcount + ($usercount * ($noticeavg + $subsavg + $joinsavg));
  291. $events -= $preuser;
  292. $events -= $pregroup;
  293. $ut = $usercount;
  294. $gt = $ut + $groupcount;
  295. $nt = $gt + ($usercount * $noticeavg);
  296. $st = $nt + ($usercount * $subsavg);
  297. $jt = $st + ($usercount * $joinsavg);
  298. // $ft = $jt + ($usercount * $favesavg);
  299. // $mt = $ft + ($usercount * $messageavg);
  300. // printfv("$events events ($ut, $gt, $nt, $st, $jt, $ft, $mt)\n");
  301. printfv("$events events ($ut, $gt, $nt, $st, $jt)\n");
  302. for ($i = 0; $i < $events; $i++)
  303. {
  304. $e = rand(0, $events);
  305. if ($e >= 0 && $e <= $ut) {
  306. printfv("$i Creating user $n\n");
  307. newUser($n);
  308. $n++;
  309. } else if ($e > $ut && $e <= $gt) {
  310. printfv("$i Creating group $g\n");
  311. newGroup($g, $n);
  312. $g++;
  313. } else if ($e > $gt && $e <= $nt) {
  314. printfv("$i Making a new notice\n");
  315. newNotice($n, $tagmax);
  316. } else if ($e > $nt && $e <= $st) {
  317. printfv("$i Making a new subscription\n");
  318. newSub($n);
  319. } else if ($e > $st && $e <= $jt) {
  320. printfv("$i Making a new group join\n");
  321. newJoin($n, $g);
  322. /* } else if ($e > $jt && $e <= $ft) {
  323. printfv("$i Making a new fave\n");
  324. newFave($n);*/
  325. /* } else if ($e > $ft && $e <= $mt) {
  326. printfv("$i Making a new message\n");
  327. newMessage($n);*/
  328. } else {
  329. printfv("No event for $i!");
  330. }
  331. }
  332. }
  333. $defaultWordsfile = '/usr/share/dict/words';
  334. $usercount = (have_option('u', 'users')) ? get_option_value('u', 'users') : 100;
  335. $groupcount = (have_option('g', 'groups')) ? get_option_value('g', 'groups') : 20;
  336. $noticeavg = (have_option('n', 'notices')) ? get_option_value('n', 'notices') : 100;
  337. $subsavg = (have_option('b', 'subscriptions')) ? get_option_value('b', 'subscriptions') : max($usercount/20, 10);
  338. $joinsavg = (have_option('j', 'joins')) ? get_option_value('j', 'joins') : 5;
  339. //$favesavg = (have_option('f', 'faves')) ? get_option_value('f', 'faves') : max($noticeavg/10, 5);
  340. //$messageavg = (have_option('m', 'messages')) ? get_option_value('m', 'messages') : max($noticeavg/10, 5);
  341. $tagmax = (have_option('t', 'tags')) ? get_option_value('t', 'tags') : 10000;
  342. $userprefix = (have_option('x', 'prefix')) ? get_option_value('x', 'prefix') : 'testuser';
  343. $groupprefix = (have_option('z', 'groupprefix')) ? get_option_value('z', 'groupprefix') : 'testgroup';
  344. $wordsfile = (have_option('w', 'words')) ? get_option_value('w', 'words') : $defaultWordsfile;
  345. if (is_readable($wordsfile)) {
  346. $words = file($wordsfile);
  347. } else {
  348. if ($wordsfile != $defaultWordsfile) {
  349. // user specified words file couldn't be read
  350. throw new Exception("Couldn't read words file: {$wordsfile}.");
  351. }
  352. $words = null;
  353. }
  354. try {
  355. //main($usercount, $groupcount, $noticeavg, $subsavg, $joinsavg, $favesavg, $messageavg, $tagmax);
  356. main($usercount, $groupcount, $noticeavg, $subsavg, $joinsavg, $tagmax);
  357. } catch (Exception $e) {
  358. printfv("Got an exception: ".$e->getMessage());
  359. }