Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
46.43% covered (danger)
46.43%
26 / 56
28.57% covered (danger)
28.57%
2 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
HistogramRangeTallier
46.43% covered (danger)
46.43%
26 / 56
28.57% covered (danger)
28.57%
2 / 7
61.43
0.00% covered (danger)
0.00%
0 / 1
 __construct
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
3.00
 addVote
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 finishTally
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
3.21
 loadJSONResult
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getJSONResult
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getHtmlResult
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
42
 getTextResult
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\SecurePoll\Talliers;
4
5use MediaWiki\Extension\SecurePoll\Exceptions\InvalidDataException;
6use Xml;
7
8class HistogramRangeTallier extends Tallier {
9    /** @var array */
10    public $histogram = [];
11    /** @var array */
12    public $sums = [];
13    /** @var array */
14    public $counts = [];
15    /** @var array|null */
16    public $averages;
17    /** @var int */
18    public $minScore;
19    /** @var int */
20    public $maxScore;
21
22    public function __construct( $context, $electionTallier, $question ) {
23        parent::__construct( $context, $electionTallier, $question );
24        $this->minScore = intval( $question->getProperty( 'min-score' ) );
25        $this->maxScore = intval( $question->getProperty( 'max-score' ) );
26        if ( $this->minScore >= $this->maxScore ) {
27            throw new InvalidDataException( __METHOD__ . ': min-score/max-score configured incorrectly' );
28        }
29
30        foreach ( $question->getOptions() as $option ) {
31            $this->histogram[$option->getId()] = array_fill(
32                $this->minScore,
33                $this->maxScore - $this->minScore + 1,
34                0
35            );
36            $this->sums[$option->getId()] = 0;
37            $this->counts[$option->getId()] = 0;
38        }
39    }
40
41    /**
42     * @inheritDoc
43     *
44     */
45    public function addVote( $scores ) {
46        foreach ( $scores as $oid => $score ) {
47            $this->histogram[$oid][$score]++;
48            $this->sums[$oid] += $score;
49            $this->counts[$oid]++;
50        }
51
52        return true;
53    }
54
55    /**
56     * @inheritDoc
57     *
58     */
59    public function finishTally() {
60        $this->averages = [];
61        foreach ( $this->sums as $oid => $sum ) {
62            if ( $this->counts[$oid] === 0 ) {
63                $this->averages[$oid] = 'N/A';
64                break;
65            }
66            $this->averages[$oid] = $sum / $this->counts[$oid];
67        }
68        arsort( $this->averages );
69    }
70
71    /**
72     * @inheritDoc
73     *
74     */
75    public function loadJSONResult( $data ) {
76        $this->averages = $data['averages'];
77        $this->histogram = $data['histogram'];
78    }
79
80    /**
81     * @inheritDoc
82     *
83     */
84    public function getJSONResult() {
85        return [
86            'averages' => $this->averages,
87            'histogram' => $this->histogram,
88        ];
89    }
90
91    /**
92     * @inheritDoc
93     * @throws InvalidDataException
94     */
95    public function getHtmlResult() {
96        $ballot = $this->election->getBallot();
97        if ( !method_exists( $ballot, 'getColumnLabels' ) ) {
98            throw new InvalidDataException( __METHOD__ . ': ballot type not supported by this tallier' );
99        }
100        $optionLabels = [];
101        foreach ( $this->question->getOptions() as $option ) {
102            $optionLabels[$option->getId()] = $option->parseMessageInline( 'text' );
103        }
104
105        // @phan-suppress-next-line PhanUndeclaredMethod Checked by is_callable
106        $labels = $ballot->getColumnLabels( $this->question );
107        $s = "<table class=\"securepoll-table\">\n" . "<tr>\n" . "<th>&#160;</th>\n";
108        foreach ( $labels as $label ) {
109            $s .= Xml::element( 'th', [], $label ) . "\n";
110        }
111        $s .= Xml::element( 'th', [], wfMessage( 'securepoll-average-score' )->text() );
112        $s .= "</tr>\n";
113
114        foreach ( $this->averages as $oid => $average ) {
115            $s .= "<tr>\n" . Xml::tags(
116                    'td',
117                    [ 'class' => 'securepoll-results-row-heading' ],
118                    $optionLabels[$oid]
119                ) . "\n";
120            foreach ( $labels as $score => $label ) {
121                $s .= Xml::element( 'td', [], $this->histogram[$oid][$score] ) . "\n";
122            }
123            $s .= Xml::element( 'td', [], $average ) . "\n";
124            $s .= "</tr>\n";
125        }
126        $s .= "</table>\n";
127
128        return $s;
129    }
130
131    /**
132     * @inheritDoc
133     *
134     */
135    public function getTextResult() {
136        return $this->getHtmlResult();
137    }
138}