Index: trunk/extensions/FlaggedRevs/maintenance/updateStats.inc |
— | — | @@ -60,7 +60,7 @@ |
61 | 61 | ); |
62 | 62 | // Get the mean edit review time |
63 | 63 | $size = 15000; // Sample size |
64 | | - $seconds = $aveRT = 0; |
| 64 | + $seconds = $aveRT = $medianRT = 0; |
65 | 65 | # Only go so far back...otherwise we will get garbage values due to |
66 | 66 | # the fact that FlaggedRevs wasn't enabled until after a while. |
67 | 67 | $installed = $dbr->selectField( 'logging', 'MIN(log_timestamp)', array('log_type' => 'review') ); |
— | — | @@ -140,38 +140,57 @@ |
141 | 141 | # For edits that started off pending, how long do they take to get reviewed? |
142 | 142 | # Get the *first* reviewed rev *after* each RC item and get the average difference. |
143 | 143 | # Only do this for revisions to pages that *were* already logged as reviewed. |
144 | | - $sql = $dbr->selectSQLText( array('revision','flaggedrevs','page','logging'), |
145 | | - array( 'UNIX_TIMESTAMP(rev_timestamp) AS rt', 'UNIX_TIMESTAMP(MIN(fr_timestamp)) AS ft', |
146 | | - 'MIN(log_timestamp) AS lt' ), |
| 144 | + $sql = $dbr->selectSQLText( array('revision','page','logging','flaggedrevs'), |
| 145 | + array( 'UNIX_TIMESTAMP(rev_timestamp) AS rt', 'UNIX_TIMESTAMP(MIN(fr_timestamp)) AS ft', 'MIN(log_timestamp)' ), |
147 | 146 | array( |
| 147 | + $timeCondition, // in time range |
148 | 148 | "rev_id BETWEEN $minRev AND $maxRev", // Better INDEX usage |
149 | | - $timeCondition, |
150 | 149 | 'rev_user = 0', // IP edits (should start off unreviewed) |
151 | | - ($mod > 1) ? "(rev_id % $mod) = 0" : "1 = 1", // Better spread |
152 | | - 'fr_page_id = rev_page AND fr_rev_id >= rev_id AND fr_timestamp > rev_timestamp', // later reviewed |
153 | | - // Check that this page was stable at the time. |
154 | | - // Assumes that reviewed pages stay reviewed (reasonable). |
155 | | - 'page_id = rev_page', // get the title |
156 | | - 'log_namespace = page_namespace AND log_title = page_title', |
157 | | - 'log_type = "review" AND log_timestamp < rev_timestamp', |
| 150 | + "(rev_id % $mod) = 0", // Better spread |
158 | 151 | ), |
159 | 152 | __METHOD__, |
160 | 153 | array( |
161 | | - 'GROUP BY' => 'rev_id', |
| 154 | + 'GROUP BY' => 'rev_id', // stats are for each edit and ID is unique |
162 | 155 | 'ORDER BY' => 'rev_id ASC', // slight bias avoidance, if any |
163 | 156 | 'LIMIT' => $size, // sample size |
164 | 157 | 'USE INDEX' => array('revision' => array('PRIMARY','rev_id'),'flaggedrevs' => 'PRIMARY','logging' => 'page_time') |
| 158 | + ), |
| 159 | + array( // Assumes title unchanged (reasonable). |
| 160 | + 'page' => array('INNER JOIN','page_id = rev_page'), // get the title |
| 161 | + // Check that this page was stable at the time... |
| 162 | + // Assumes that reviewed pages stay reviewed (reasonable). |
| 163 | + 'logging' => array('INNER JOIN','log_namespace = page_namespace AND log_title = page_title |
| 164 | + AND log_type = "review" AND log_timestamp < rev_timestamp'), |
| 165 | + // Check *if* it was later reviewed |
| 166 | + 'flaggedrevs' => array('LEFT JOIN', 'fr_page_id = rev_page AND fr_rev_id >= rev_id AND fr_timestamp > rev_timestamp'), |
165 | 167 | ) |
166 | 168 | ); |
167 | 169 | # Actually run the query... |
168 | 170 | $res = $dbr->doQuery( $sql, __METHOD__ ); |
169 | 171 | if( $count = $dbr->numRows($res) ) { |
| 172 | + $censored = 0; |
| 173 | + $times = array(); |
170 | 174 | # Get the sum of elapsed times |
171 | 175 | while( $row = $dbr->fetchObject($res) ) { |
172 | | - $seconds += ($row->ft - $row->rt); |
| 176 | + # Reviewed: just subtract the times |
| 177 | + if( $row->ft ) { |
| 178 | + $seconds += ($row->ft - $row->rt); |
| 179 | + # Not reviewed: censored data |
| 180 | + } else { |
| 181 | + $seconds += ($now - $row->rt); |
| 182 | + $censored++; |
| 183 | + } |
| 184 | + $times[] = $seconds; |
173 | 185 | #echo( "\nedit:".$row->rt . "\treviewed:" . $row->ft ); |
174 | 186 | } |
175 | | - $aveRT = $seconds/$count; // average |
| 187 | + $aveRT = $seconds/($count - $censored); // sample mean |
| 188 | + sort($times); // order smallest -> largest |
| 189 | + // Sample median |
| 190 | + if( count($times) % 2 == 0 ) { |
| 191 | + $medianRT = ($times[count($times)/2-1] + $times[count($times)/2])/2; |
| 192 | + } else { |
| 193 | + $medianRT = $times[floor(count($times)/2)]; |
| 194 | + } |
176 | 195 | } |
177 | 196 | // Save the data |
178 | 197 | $dbw = wfGetDB( DB_MASTER ); |
— | — | @@ -195,7 +214,7 @@ |
196 | 215 | ); |
197 | 216 | } |
198 | 217 | $dbw->replace( 'flaggedrevs_stats2', array('stat_id'), |
199 | | - array('stat_id' => 1, 'ave_review_time' => $aveRT, 'ave_pending_time' => $avePET), |
| 218 | + array('stat_id' => 1, 'ave_review_time' => $aveRT, 'med_review_time' => $medianRT, 'ave_pending_time' => $avePET), |
200 | 219 | __METHOD__ |
201 | 220 | ); |
202 | 221 | $dbw->commit(); |
— | — | @@ -222,6 +241,7 @@ |
223 | 242 | "CREATE TABLE $flaggedrevs_stats2 ( |
224 | 243 | stat_id INTEGER UNSIGNED NOT NULL DEFAULT 1 PRIMARY KEY, |
225 | 244 | ave_review_time INTEGER UNSIGNED NOT NULL DEFAULT 0, |
| 245 | + med_review_time INTEGER UNSIGNED NOT NULL DEFAULT 0, |
226 | 246 | ave_pending_time INTEGER UNSIGNED NOT NULL DEFAULT 0 |
227 | 247 | );" |
228 | 248 | ); |
Index: trunk/extensions/FlaggedRevs/language/ValidationStatistics.i18n.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | 'validationstatistics' => 'Validation statistics', |
13 | 13 | 'validationstatistics-users' => '\'\'\'{{SITENAME}}\'\'\' currently has \'\'\'[[Special:ListUsers/editor|$1]]\'\'\' {{PLURAL:$1|user|users}} with [[{{MediaWiki:Validationpage}}|Editor]] rights |
14 | 14 | and \'\'\'[[Special:ListUsers/reviewer|$2]]\'\'\' {{PLURAL:$2|user|users}} with [[{{MediaWiki:Validationpage}}|Reviewer]] rights.', |
15 | | - 'validationstatistics-time' => 'The average wait for edits by \'\'users that have not logged in\'\' is \'\'\'$1\'\'\'. |
| 15 | + 'validationstatistics-time' => 'The average wait for edits by \'\'users that have not logged in\'\' is \'\'\'$1\'\'\'; the median is \'\'\'$3\'\'\'. |
16 | 16 | The average lag for [[Special:OldReviewedPages|outdated pages]] is \'\'\'$2\'\'\'.', |
17 | 17 | 'validationstatistics-table' => "Statistics for each namespace are shown below, ''excluding'' redirect pages. |
18 | 18 | ''Outdated'' pages are those with edits newer than the stable version. |
— | — | @@ -822,8 +822,6 @@ |
823 | 823 | $messages['ru'] = array( |
824 | 824 | 'validationstatistics' => 'Статистика проверок', |
825 | 825 | 'validationstatistics-users' => "В проекте {{SITENAME}} на данный момент '''[[Special:ListUsers/editor|$1]]''' {{plural:$1|участник|участника|участников}} имеют права [[{{MediaWiki:Validationpage}}|«редактора»]] и '''$2''' {{plural:$2|участник|участника|участников}} имеют права [[{{MediaWiki:Validationpage}}|«проверяющего»]].", |
826 | | - 'validationstatistics-time' => "Среднее ожидание правок от ''участников, которые не авторизовались'' равно '''$1'''. |
827 | | -Средняя задержка для [[Special:OldReviewedPages|устаревших страниц]] равна '''$2'''.", |
828 | 826 | 'validationstatistics-table' => "Ниже представлена статистика по каждому пространству имён. Перенаправления из подсчётов исключены. |
829 | 827 | ''Устаревшими'' называются страницы, имеющие правки после стабильной версии. |
830 | 828 | Если стабильная версия является последней, то страница называется ''синхронизированной''. |
Index: trunk/extensions/FlaggedRevs/specialpages/ValidationStatistics_body.php |
— | — | @@ -23,13 +23,14 @@ |
24 | 24 | $ec = $this->getEditorCount(); |
25 | 25 | $rc = $this->getReviewerCount(); |
26 | 26 | $mt = $this->getMeanReviewWait(); |
| 27 | + $mdt = $this->getMedianReviewWait(); |
27 | 28 | $pt = $this->getMeanPendingWait(); |
28 | 29 | |
29 | 30 | $wgOut->addWikiText( wfMsgExt( 'validationstatistics-users', array( 'parsemag' ), |
30 | 31 | $wgLang->formatnum($ec), $wgLang->formatnum($rc) ) |
31 | 32 | ); |
32 | 33 | $wgOut->addWikiText( wfMsgExt( 'validationstatistics-time', array( 'parsemag' ), |
33 | | - $wgLang->formatTimePeriod($mt), $wgLang->formatTimePeriod($pt) ) |
| 34 | + $wgLang->formatTimePeriod($mt), $wgLang->formatTimePeriod($pt), $wgLang->formatTimePeriod($mdt) ) |
34 | 35 | ); |
35 | 36 | |
36 | 37 | if( !$this->readyForQuery() ) { |
— | — | @@ -150,6 +151,11 @@ |
151 | 152 | return $this->db->selectField( 'flaggedrevs_stats2', 'ave_review_time' ); |
152 | 153 | } |
153 | 154 | |
| 155 | + protected function getMedianReviewWait() { |
| 156 | + if( !$this->db->tableExists( 'flaggedrevs_stats2' ) ) return '-'; |
| 157 | + return $this->db->selectField( 'flaggedrevs_stats2', 'med_review_time' ); |
| 158 | + } |
| 159 | + |
154 | 160 | protected function getMeanPendingWait() { |
155 | 161 | if( !$this->db->tableExists( 'flaggedrevs_stats2' ) ) return '-'; |
156 | 162 | return $this->db->selectField( 'flaggedrevs_stats2', 'ave_pending_time' ); |