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 MediaWiki\Xml\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    /** @inheritDoc */
23    public function __construct( $context, $electionTallier, $question ) {
24        parent::__construct( $context, $electionTallier, $question );
25        $this->minScore = intval( $question->getProperty( 'min-score' ) );
26        $this->maxScore = intval( $question->getProperty( 'max-score' ) );
27        if ( $this->minScore >= $this->maxScore ) {
28            throw new InvalidDataException( __METHOD__ . ': min-score/max-score configured incorrectly' );
29        }
30
31        foreach ( $question->getOptions() as $option ) {
32            $this->histogram[$option->getId()] = array_fill(
33                $this->minScore,
34                $this->maxScore - $this->minScore + 1,
35                0
36            );
37            $this->sums[$option->getId()] = 0;
38            $this->counts[$option->getId()] = 0;
39        }
40    }
41
42    /**
43     * @inheritDoc
44     *
45     */
46    public function addVote( $scores ) {
47        foreach ( $scores as $oid => $score ) {
48            $this->histogram[$oid][$score]++;
49            $this->sums[$oid] += $score;
50            $this->counts[$oid]++;
51        }
52
53        return true;
54    }
55
56    /**
57     * @inheritDoc
58     *
59     */
60    public function finishTally() {
61        $this->averages = [];
62        foreach ( $this->sums as $oid => $sum ) {
63            if ( $this->counts[$oid] === 0 ) {
64                $this->averages[$oid] = 'N/A';
65                break;
66            }
67            $this->averages[$oid] = $sum / $this->counts[$oid];
68        }
69        arsort( $this->averages );
70    }
71
72    /**
73     * @inheritDoc
74     *
75     */
76    public function loadJSONResult( $data ) {
77        $this->averages = $data['averages'];
78        $this->histogram = $data['histogram'];
79    }
80
81    /**
82     * @inheritDoc
83     *
84     */
85    public function getJSONResult() {
86        return [
87            'averages' => $this->averages,
88            'histogram' => $this->histogram,
89        ];
90    }
91
92    /**
93     * @inheritDoc
94     * @throws InvalidDataException
95     */
96    public function getHtmlResult() {
97        $ballot = $this->election->getBallot();
98        if ( !method_exists( $ballot, 'getColumnLabels' ) ) {
99            throw new InvalidDataException( __METHOD__ . ': ballot type not supported by this tallier' );
100        }
101        $optionLabels = [];
102        foreach ( $this->question->getOptions() as $option ) {
103            $optionLabels[$option->getId()] = $option->parseMessageInline( 'text' );
104        }
105
106        // @phan-suppress-next-line PhanUndeclaredMethod Checked by is_callable
107        $labels = $ballot->getColumnLabels( $this->question );
108        $s = "<table class=\"securepoll-table\">\n" . "<tr>\n" . "<th>&#160;</th>\n";
109        foreach ( $labels as $label ) {
110            $s .= Xml::element( 'th', [], $label ) . "\n";
111        }
112        $s .= Xml::element( 'th', [], wfMessage( 'securepoll-average-score' )->text() );
113        $s .= "</tr>\n";
114
115        foreach ( $this->averages as $oid => $average ) {
116            $s .= "<tr>\n" . Xml::tags(
117                    'td',
118                    [ 'class' => 'securepoll-results-row-heading' ],
119                    $optionLabels[$oid]
120                ) . "\n";
121            foreach ( $labels as $score => $label ) {
122                $s .= Xml::element( 'td', [], $this->histogram[$oid][$score] ) . "\n";
123            }
124            $s .= Xml::element( 'td', [], $average ) . "\n";
125            $s .= "</tr>\n";
126        }
127        $s .= "</table>\n";
128
129        return $s;
130    }
131
132    /**
133     * @inheritDoc
134     *
135     */
136    public function getTextResult() {
137        return $this->getHtmlResult();
138    }
139}