Index: trunk/extensions/FlaggedRevs/language/RatingHistory.i18n.php |
— | — | @@ -20,7 +20,8 @@ |
21 | 21 | 'ratinghistory-3years' => 'last 3 years', |
22 | 22 | 'ratinghistory-chart' => 'Reader feedback rating over time', |
23 | 23 | 'ratinghistory-users' => 'Users who gave ratings', |
24 | | - 'ratinghistory-graph' => '$2 of "$3" ($1 {{PLURAL:$1|review|reviews}})', |
| 24 | + 'ratinghistory-graph' => '$2 of "$3" ($1 {{PLURAL:$1|review|reviews}}) [μ=$4; σ=$5]', |
| 25 | + 'readerfeedback-svg' => 'View as SVG', |
25 | 26 | 'ratinghistory-none' => 'There is not enough reader feedback data available for graphs at this time.', |
26 | 27 | 'ratinghistory-legend' => 'The \'\'\'daily average rating\'\'\' <font color="blue">\'\'(blue)\'\'</font> and |
27 | 28 | \'\'\'running average rating\'\'\' <font color="green">\'\'(green)\'\'</font> are graphed below, by date. The |
Index: trunk/extensions/FlaggedRevs/specialpages/RatingHistory_body.php |
— | — | @@ -51,7 +51,7 @@ |
52 | 52 | $this->dScale = 20; |
53 | 53 | # Thank voters |
54 | 54 | if( ReaderFeedback::userAlreadyVoted( $this->page ) ) { |
55 | | - $wgOut->setSubtitle( wfMsgExt('ratinghistory-thanks','parse') ); |
| 55 | + $wgOut->setSubtitle( wfMsgExt('ratinghistory-thanks','parseinline') ); |
56 | 56 | } |
57 | 57 | $this->showForm(); |
58 | 58 | $this->showHeader(); |
— | — | @@ -138,7 +138,14 @@ |
139 | 139 | case 'png': |
140 | 140 | if( $exists ) { |
141 | 141 | $data = true; |
142 | | - $wgOut->addHTML( "<h3>" . wfMsgHtml("readerfeedback-$tag") . "</h3>\n" ); |
| 142 | + // Add link for users with non-shitty browsers to see SVG itself |
| 143 | + $viewLink = ""; |
| 144 | + if( $sExt === 'svg' ) { |
| 145 | + $svgUrl = $this->getUrlPath( $tag, 'svg' ); |
| 146 | + $viewLink = " <small>[<a href='".$svgUrl."'>". |
| 147 | + wfMsgHtml("readerfeedback-svg")."</a>]</small>"; |
| 148 | + } |
| 149 | + $wgOut->addHTML( "<h3>" . wfMsgHtml("readerfeedback-$tag") . "$viewLink</h3>\n" ); |
143 | 150 | $wgOut->addHTML( |
144 | 151 | Xml::openElement( 'div', array('class' => 'fr_reader_feedback_graph') ) . |
145 | 152 | Xml::openElement( 'img', array('src' => $url,'alt' => $tag) ) . |
— | — | @@ -193,7 +200,7 @@ |
194 | 201 | } |
195 | 202 | // Define the data using the DB rows |
196 | 203 | $totalVal = $totalCount = $n = 0; |
197 | | - $res = $this->doQuery( $tag ); |
| 204 | + list($res,$u,$maxC) = $this->doQuery( $tag ); |
198 | 205 | // Label spacing |
199 | 206 | if( $row = $res->fetchObject() ) { |
200 | 207 | $lower = wfTimestamp( TS_UNIX, $row->rfh_date ); |
— | — | @@ -204,7 +211,6 @@ |
205 | 212 | $res->seek( 0 ); |
206 | 213 | } |
207 | 214 | $dates = $drating = $arating = $dcount = ""; |
208 | | - $n = 0; |
209 | 215 | while( $row = $res->fetchObject() ) { |
210 | 216 | $totalVal += (int)$row->rfh_total; |
211 | 217 | $totalCount += (int)$row->rfh_count; |
— | — | @@ -261,7 +267,7 @@ |
262 | 268 | $data = array(); |
263 | 269 | $totalVal = $totalCount = $n = 0; |
264 | 270 | // Define the data using the DB rows |
265 | | - $res = $this->doQuery( $tag ); |
| 271 | + list($res,$u,$maxC) = $this->doQuery( $tag ); |
266 | 272 | // Label spacing |
267 | 273 | if( $row = $res->fetchObject() ) { |
268 | 274 | $lower = wfTimestamp( TS_UNIX, $row->rfh_date ); |
— | — | @@ -365,9 +371,9 @@ |
366 | 372 | $plot->maxY = 5; |
367 | 373 | // Define the data using the DB rows |
368 | 374 | $dataX = $dave = $rave = $dcount = array(); |
369 | | - $totalVal = $totalCount = $n = 0; |
| 375 | + $totalVal = $totalCount = $sd = $pts = $n = 0; |
370 | 376 | // Define the data using the DB rows |
371 | | - $res = $this->doQuery( $tag ); |
| 377 | + list($res,$u,$maxC) = $this->doQuery( $tag ); |
372 | 378 | // Label spacing |
373 | 379 | if( $row = $res->fetchObject() ) { |
374 | 380 | $lower = wfTimestamp( TS_UNIX, $row->rfh_date ); |
— | — | @@ -378,11 +384,13 @@ |
379 | 385 | $res->seek( 0 ); |
380 | 386 | } |
381 | 387 | while( $row = $res->fetchObject() ) { |
| 388 | + $pts++; |
382 | 389 | $totalVal += (int)$row->rfh_total; |
383 | 390 | $totalCount += (int)$row->rfh_count; |
384 | 391 | $dayCount = (real)$row->rfh_count; |
385 | | - // Nudge values up by 1 |
| 392 | + // Nudge values up by 1 to fit [1,5] |
386 | 393 | $dayAve = 1 + (real)$row->rfh_total/(real)$row->rfh_count; |
| 394 | + $sd += pow($dayAve - $u,2); |
387 | 395 | $cumAve = 1 + (real)$totalVal/(real)$totalCount; |
388 | 396 | $year = intval( substr( $row->rfh_date, 0, 4 ) ); |
389 | 397 | $month = intval( substr( $row->rfh_date, 4, 2 ) ); |
— | — | @@ -417,9 +425,13 @@ |
418 | 426 | $lastRAve = $cumAve; |
419 | 427 | } |
420 | 428 | // Minimum sample size |
421 | | - if( count($dataX) < 2 ) { |
| 429 | + if( $pts < 2 ) { |
422 | 430 | return false; |
423 | 431 | } |
| 432 | + $sd = sqrt($sd/$pts); |
| 433 | + // Round values for display |
| 434 | + $sd = round( $sd, 3 ); |
| 435 | + $u = round( $u, 3 ); |
424 | 436 | // Fit to [0,4] |
425 | 437 | foreach( $dcount as $x => $c ) { |
426 | 438 | $dcount[$x] = $c/$this->dScale; |
— | — | @@ -434,9 +446,9 @@ |
435 | 447 | $plot->format['rave'] = array( 'style' => 'stroke:green; stroke-width:1;' ); |
436 | 448 | $plot->format['dcount'] = array( 'style' => 'stroke:red; stroke-width:1;' ); |
437 | 449 | #'attributes' => "marker-end='url(#circle)'"); |
438 | | - $pageText = $wgContLang->truncate( $this->page->getPrefixedText(), 70, '...' ); |
| 450 | + $pageText = $wgContLang->truncate( $this->page->getPrefixedText(), 60, '...' ); |
439 | 451 | $plot->title = wfMsgExt('ratinghistory-graph',array('parsemag','content'), |
440 | | - $totalCount, wfMsgForContent("readerfeedback-$tag"), $pageText ); |
| 452 | + $totalCount, wfMsgForContent("readerfeedback-$tag"), $pageText, $u, $sd ); |
441 | 453 | $plot->styleTitle = 'font-family: sans-serif; font-weight: bold; font-size: 12pt;'; |
442 | 454 | $plot->backgroundStyle = 'fill:#F0F0F0;'; |
443 | 455 | // extra code for markers |
— | — | @@ -487,7 +499,18 @@ |
488 | 500 | __METHOD__, |
489 | 501 | array( 'ORDER BY' => 'rfh_date ASC' ) |
490 | 502 | ); |
491 | | - return $res; |
| 503 | + # Get max count and average rating |
| 504 | + $total = $count = $ave = $maxC = 0; |
| 505 | + if( $dbr->numRows($res) ) { |
| 506 | + while( $row = $dbr->fetchObject($res) ) { |
| 507 | + $total += (int)$row->rfh_total; |
| 508 | + $count += (int)$row->rfh_count; |
| 509 | + if( $row->rfh_count > $maxC ) $maxC = intval($row->rfh_count); |
| 510 | + } |
| 511 | + $ave = 1+$total/$count; // Offset to [1,5] |
| 512 | + $res->seek( 0 ); |
| 513 | + } |
| 514 | + return array($res,$ave,$maxC); |
492 | 515 | } |
493 | 516 | |
494 | 517 | /** |
— | — | @@ -505,11 +528,12 @@ |
506 | 529 | /** |
507 | 530 | * Get the url to where the corresponding graph file should be |
508 | 531 | * @param string $tag |
| 532 | + * @param string $ext |
509 | 533 | * @returns string |
510 | 534 | */ |
511 | | - public function getUrlPath( $tag ) { |
| 535 | + public function getUrlPath( $tag, $ext='' ) { |
512 | 536 | global $wgUploadPath; |
513 | | - $rel = self::getRelPath( $tag ); |
| 537 | + $rel = self::getRelPath( $tag, $ext ); |
514 | 538 | return "{$wgUploadPath}/graphs/{$rel}"; |
515 | 539 | } |
516 | 540 | |