r58801 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r58800‎ | r58801 | r58802 >
Date:03:11, 9 November 2009
Author:tstarling
Status:deferred
Tags:
Comment:
* Added histogram/range tallier
* Give the Tallier access to the ElectionTallier parent
* Fixed various problems with r58430:
* Better format for $links in EntryPage
* Made the translate subpage public and accessible after close since this is the only interface available for read-only access to i18n data.
* Show the link text even if the link is disabled, so that the links are vertically aligned
* Re-added wfLoadExtensionMessages() call, inexplicably removed. SecurePoll works best with MediaWiki 1.15.
Modified paths:
  • /trunk/extensions/SecurePoll/SecurePoll.i18n.php (modified) (history)
  • /trunk/extensions/SecurePoll/SecurePoll.php (modified) (history)
  • /trunk/extensions/SecurePoll/cli/cli.inc (modified) (history)
  • /trunk/extensions/SecurePoll/includes/ballots/RadioRangeBallot.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/main/Base.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/main/Context.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/pages/EntryPage.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/pages/ListPage.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/talliers/ElectionTallier.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/talliers/HistogramRangeTallier.php (added) (history)
  • /trunk/extensions/SecurePoll/includes/talliers/PairwiseTallier.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/talliers/PluralityTallier.php (modified) (history)
  • /trunk/extensions/SecurePoll/includes/talliers/Tallier.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SecurePoll/SecurePoll.i18n.php
@@ -100,8 +100,8 @@
101101 'securepoll-strike-error' => 'Error performing strike/unstrike: $1',
102102 'securepoll-strike-token-mismatch' => 'Session data lost',
103103 'securepoll-details-link' => 'Details',
104 - 'securepoll-votername-local' => '[[User:$1|$1]]',
105 - 'securepoll-votername-remote' => '$1',
 104+ 'securepoll-voter-name-local' => '[[User:$1|$1]]',
 105+ 'securepoll-voter-name-remote' => '$1',
106106
107107 # Details page
108108 # Mostly for admins
@@ -162,6 +162,7 @@
163163 'securepoll-pairwise-victories' => 'Pairwise victory matrix',
164164 'securepoll-strength-matrix' => 'Path strength matrix',
165165 'securepoll-ranks' => 'Final ranking',
 166+ 'securepoll-average-score' => 'Average score',
166167 );
167168
168169 /** Message documentation (Message documentation)
Index: trunk/extensions/SecurePoll/SecurePoll.php
@@ -89,6 +89,7 @@
9090
9191 # talliers
9292 'SecurePoll_ElectionTallier' => "$dir/includes/talliers/ElectionTallier.php",
 93+ 'SecurePoll_HistogramRangeTallier' => "$dir/includes/talliers/HistogramRangeTallier.php",
9394 'SecurePoll_PairwiseTallier' => "$dir/includes/talliers/PairwiseTallier.php",
9495 'SecurePoll_PluralityTallier' => "$dir/includes/talliers/PluralityTallier.php",
9596 'SecurePoll_SchulzeTallier' => "$dir/includes/talliers/SchulzeTallier.php",
Index: trunk/extensions/SecurePoll/includes/pages/EntryPage.php
@@ -30,6 +30,28 @@
3131 * Pager for an election list. See TablePager documentation.
3232 */
3333 class SecurePoll_ElectionPager extends TablePager {
 34+ var $subpages = array(
 35+ 'vote' => array(
 36+ 'public' => true,
 37+ 'visible-after-close' => false,
 38+ ),
 39+ 'translate' => array(
 40+ 'public' => true,
 41+ 'visible-after-close' => true,
 42+ ),
 43+ 'list' => array(
 44+ 'public' => true,
 45+ 'visible-after-close' => true,
 46+ ),
 47+ 'dump' => array(
 48+ 'public' => false,
 49+ 'visible-after-close' => true,
 50+ ),
 51+ 'tally' => array(
 52+ 'public' => false,
 53+ 'visible-after-close' => true,
 54+ ),
 55+ );
3456 var $fields = array(
3557 'el_title',
3658 'el_start_date',
@@ -64,7 +86,7 @@
6587 * @return String
6688 * @see TablePager::getRowClass()
6789 */
68 - function getRowClass( $row ){
 90+ function getRowClass( $row ) {
6991 return $row->el_end_date > wfTimestampNow( TS_DB )
7092 ? 'securepoll-election-open'
7193 : 'securepoll-election-closed';
@@ -83,7 +105,7 @@
84106 }
85107 }
86108
87 - function formatRow( $row ){
 109+ function formatRow( $row ) {
88110 global $wgUser;
89111 $id = $row->el_entity;
90112 $this->election = $this->entryPage->context->getElection( $id );
@@ -98,30 +120,23 @@
99121 function getLinks() {
100122 global $wgUser;
101123 $id = $this->mCurrentRow->el_entity;
102 -
103 - $links = array(
104 - # visible to non-admins
105 - # visible after election is closed
106 - 'vote' => array( true, false ),
107 - 'translate' => array( false, false ),
108 - 'list' => array( true, true ),
109 - 'dump' => array( false, true ),
110 - 'tally' => array( false, true ),
111 - );
112124
113125 $s = '';
114126 $sep = wfMsg( 'pipe-separator' );
115127 $skin = $wgUser->getSkin();
116 - foreach ( $links as $subpage => $criteria ) {
117 - if( ( $this->isAdmin || $criteria[0] )
118 - && ( !$this->election->isFinished() || $criteria[1] )
119 - ){
 128+ foreach ( $this->subpages as $subpage => $props ) {
 129+ $linkText = wfMsgExt( "securepoll-subpage-$subpage", 'parseinline' );
 130+ if ( $s !== '' ) {
 131+ $s .= $sep;
 132+ }
 133+ if( ( $this->isAdmin || $props['public'] )
 134+ && ( !$this->election->isFinished() || $props['visible-after-close'] ) )
 135+ {
120136 $title = $this->entryPage->parent->getTitle( "$subpage/$id" );
121 - $linkText = wfMsgExt( "securepoll-subpage-$subpage", 'parseinline' );
122 - if ( $s !== '' ) {
123 - $s .= $sep;
124 - }
125137 $s .= $skin->makeKnownLinkObj( $title, $linkText );
 138+ } else {
 139+ $s .= "<span class=\"securepoll-link-disabled\">" .
 140+ $linkText . "</span>";
126141 }
127142 }
128143 return $s;
Index: trunk/extensions/SecurePoll/includes/pages/ListPage.php
@@ -269,8 +269,8 @@
270270 ) );
271271 case 'vote_voter_name':
272272 $msg = $voter->isRemote()
273 - ? 'securepoll-votername-remote'
274 - : 'securepoll-votername-local';
 273+ ? 'securepoll-voter-name-remote'
 274+ : 'securepoll-voter-name-local';
275275 return wfMsgExt(
276276 $msg,
277277 'parseinline',
Index: trunk/extensions/SecurePoll/includes/talliers/Tallier.php
@@ -6,7 +6,7 @@
77 * questions.
88 */
99 abstract class SecurePoll_Tallier {
10 - var $context, $question, $optionsById;
 10+ var $context, $question, $electionTallier, $election, $optionsById;
1111
1212 abstract function addVote( $scores );
1313 abstract function getHtmlResult();
@@ -14,20 +14,24 @@
1515
1616 abstract function finishTally();
1717
18 - static function factory( $context, $type, $question ) {
 18+ static function factory( $context, $type, $electionTallier, $question ) {
1919 switch ( $type ) {
2020 case 'plurality':
21 - return new SecurePoll_PluralityTallier( $context, $question );
 21+ return new SecurePoll_PluralityTallier( $context, $electionTallier, $question );
2222 case 'schulze':
23 - return new SecurePoll_SchulzeTallier( $context, $question );
 23+ return new SecurePoll_SchulzeTallier( $context, $electionTallier, $question );
 24+ case 'histogram-range':
 25+ return new SecurePoll_HistogramRangeTallier( $context, $electionTallier, $question );
2426 default:
2527 throw new MWException( "Invalid tallier type: $type" );
2628 }
2729 }
2830
29 - function __construct( $context, $question ) {
 31+ function __construct( $context, $electionTallier, $question ) {
3032 $this->context = $context;
3133 $this->question = $question;
 34+ $this->electionTallier = $electionTallier;
 35+ $this->election = $electionTallier->election;
3236 foreach ( $this->question->getOptions() as $option ) {
3337 $this->optionsById[$option->getId()] = $option;
3438 }
Index: trunk/extensions/SecurePoll/includes/talliers/ElectionTallier.php
@@ -32,7 +32,7 @@
3333 $this->talliers = array();
3434 $tallyType = $this->election->getTallyType();
3535 foreach ( $questions as $question ) {
36 - $tallier = $this->context->newTallier( $tallyType, $question );
 36+ $tallier = $this->context->newTallier( $tallyType, $this, $question );
3737 if ( !$tallier ) {
3838 throw new MWException( 'Invalid tally type' );
3939 }
Index: trunk/extensions/SecurePoll/includes/talliers/PairwiseTallier.php
@@ -10,8 +10,8 @@
1111 var $abbrevs;
1212 var $rowLabels = array();
1313
14 - function __construct( $context, $question ) {
15 - parent::__construct( $context, $question );
 14+ function __construct( $context, $electionTallier, $question ) {
 15+ parent::__construct( $context, $electionTallier, $question );
1616 $this->optionIds = array();
1717 foreach ( $question->getOptions() as $option ) {
1818 $this->optionIds[] = $option->getId();
Index: trunk/extensions/SecurePoll/includes/talliers/PluralityTallier.php
@@ -6,8 +6,8 @@
77 class SecurePoll_PluralityTallier extends SecurePoll_Tallier {
88 var $tally = array();
99
10 - function __construct( $context, $question ) {
11 - parent::__construct( $context, $question );
 10+ function __construct( $context, $electionTallier, $question ) {
 11+ parent::__construct( $context, $electionTallier, $question );
1212 foreach ( $question->getOptions() as $option ) {
1313 $this->tally[$option->getId()] = 0;
1414 }
Index: trunk/extensions/SecurePoll/includes/talliers/HistogramRangeTallier.php
@@ -0,0 +1,86 @@
 2+<?php
 3+
 4+class SecurePoll_HistogramRangeTallier extends SecurePoll_Tallier {
 5+ var $histogram = array();
 6+ var $sums = array();
 7+ var $counts = array();
 8+ var $averages;
 9+ var $minScore, $maxScore;
 10+
 11+ function __construct( $context, $electionTallier, $question ) {
 12+ parent::__construct( $context, $electionTallier, $question );
 13+ $this->minScore = intval( $question->getProperty( 'min-score' ) );
 14+ $this->maxScore = intval( $question->getProperty( 'max-score' ) );
 15+ if ( $this->minScore >= $this->maxScore ) {
 16+ throw new MWException( __METHOD__.': min-score/max-score configured incorrectly' );
 17+ }
 18+
 19+ foreach ( $question->getOptions() as $option ) {
 20+ $this->histogram[$option->getId()] =
 21+ array_fill( $this->minScore, $this->maxScore - $this->minScore + 1, 0 );
 22+ $this->sums[$option->getId()] = 0;
 23+ $this->counts[$option->getId()] = 0;
 24+ }
 25+ }
 26+
 27+ function addVote( $scores ) {
 28+ foreach ( $scores as $oid => $score ) {
 29+ $this->histogram[$oid][$score] ++;
 30+ $this->sums[$oid] += $score;
 31+ $this->counts[$oid] ++;
 32+ }
 33+ return true;
 34+ }
 35+
 36+ function finishTally() {
 37+ $this->averages = array();
 38+ foreach ( $this->sums as $oid => $sum ) {
 39+ if ( $this->counts[$oid] === 0 ) {
 40+ $this->averages[$oid] = 'N/A';
 41+ break;
 42+ }
 43+ $this->averages[$oid] = $sum / $this->counts[$oid];
 44+ }
 45+ arsort( $this->averages );
 46+ }
 47+
 48+ function getHtmlResult() {
 49+ $ballot = $this->election->getBallot();
 50+ if ( !is_callable( array( $ballot, 'getColumnLabels' ) ) ) {
 51+ throw new MWException( __METHOD__.': ballot type not supported by this tallier' );
 52+ }
 53+ $optionLabels = array();
 54+ foreach ( $this->question->getOptions() as $option ) {
 55+ $optionLabels[$option->getId()] = $option->getMessage( 'text' );
 56+ }
 57+
 58+ $labels = $ballot->getColumnLabels( $this->question );
 59+ $s = "<table class=\"securepoll-table\">\n" .
 60+ "<tr>\n" .
 61+ "<th>&nbsp;</th>\n";
 62+ foreach ( $labels as $label ) {
 63+ $s .= Xml::element( 'th', array(), $label ) . "\n";
 64+ }
 65+ $s .= Xml::element( 'th', array(), wfMsg( 'securepoll-average-score' ) );
 66+ $s .= "</tr>\n";
 67+
 68+ foreach ( $this->averages as $oid => $average ) {
 69+ $s .= "<tr>\n" .
 70+ Xml::element( 'td', array( 'class' => 'securepoll-results-row-heading' ),
 71+ $optionLabels[$oid] ) .
 72+ "\n";
 73+ foreach ( $labels as $score => $label ) {
 74+ $s .= Xml::element( 'td', array(), $this->histogram[$oid][$score] ) . "\n";
 75+ }
 76+ $s .= Xml::element( 'td', array(), $average ) . "\n";
 77+ $s .= "</tr>\n";
 78+ }
 79+ $s .= "</table>\n";
 80+ return $s;
 81+ }
 82+
 83+ function getTextResult() {
 84+ throw new MWException( __METHOD__.': not yet implemented' );
 85+ }
 86+}
 87+
Property changes on: trunk/extensions/SecurePoll/includes/talliers/HistogramRangeTallier.php
___________________________________________________________________
Name: svn:eol-style
188 + native
Index: trunk/extensions/SecurePoll/includes/ballots/RadioRangeBallot.php
@@ -86,6 +86,7 @@
8787 foreach ( $labels as $label ) {
8888 $s .= Xml::element( 'th', array(), $label ) . "\n";
8989 }
 90+ $s .= "</tr>\n";
9091 $defaultScore = $question->getProperty( 'default-score' );
9192
9293 foreach ( $options as $option ) {
@@ -179,6 +180,7 @@
180181 list( $min, $max ) = $this->getMinMax( $questions[$qid] );
181182 if ( $score < $min || $score > $max ) {
182183 wfDebug( __METHOD__.": score out of range\n" );
 184+ return false;
183185 }
184186 $scores[$qid][$oid] = $score;
185187 }
Index: trunk/extensions/SecurePoll/includes/main/Base.php
@@ -36,6 +36,8 @@
3737 public function execute( $paramString ) {
3838 global $wgOut, $wgUser, $wgRequest, $wgScriptPath;
3939
 40+ wfLoadExtensionMessages( 'SecurePoll' );
 41+
4042 $this->setHeaders();
4143 $wgOut->addLink( array(
4244 'rel' => 'stylesheet',
Index: trunk/extensions/SecurePoll/includes/main/Context.php
@@ -251,8 +251,8 @@
252252 return SecurePoll_Crypt::factory( $this, $type, $election );
253253 }
254254
255 - function newTallier( $type, $question ) {
256 - return SecurePoll_Tallier::factory( $this, $type, $question );
 255+ function newTallier( $type, $electionTallier, $question ) {
 256+ return SecurePoll_Tallier::factory( $this, $type, $electionTallier, $question );
257257 }
258258
259259 function newBallot( $type, $election ) {
Index: trunk/extensions/SecurePoll/cli/cli.inc
@@ -14,3 +14,5 @@
1515
1616 require( $IP . '/maintenance/commandLine.inc' );
1717
 18+wfLoadExtensionMessages( 'SecurePoll' );
 19+

Follow-up revisions

RevisionCommit summaryAuthorDate
r58802Merging r58282 through r58801 from trunk for AUSC election tallytstarling03:16, 9 November 2009
r58805follow-up r58801: Change message keys here tooraymond05:18, 9 November 2009

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r58430Usability tweaks to SecurePoll from feedback on enwiki:...happy-melon18:19, 2 November 2009

Status & tagging log